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 "SkCanvas.h"
30#include "platform/graphics/BitmapImage.h"
31#include "platform/graphics/DisplayList.h"
32#include "platform/graphics/ImageBuffer.h"
33#include "platform/graphics/skia/NativeImageSkia.h"
34#include "third_party/skia/include/core/SkBitmapDevice.h"
35#include <gtest/gtest.h>
36
37using namespace WebCore;
38
39namespace {
40
41#define EXPECT_EQ_RECT(a, b) \
42    EXPECT_EQ(a.x(), b.x()); \
43    EXPECT_EQ(a.y(), b.y()); \
44    EXPECT_EQ(a.width(), b.width()); \
45    EXPECT_EQ(a.height(), b.height());
46
47#define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
48{ \
49    SkAutoLockPixels locker(bitmap); \
50    for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \
51        for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \
52            int alpha = *bitmap.getAddr32(x, y) >> 24; \
53            EXPECT_EQ(255, alpha); \
54        } \
55}
56
57#define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \
58{ \
59    SkAutoLockPixels locker(bitmap); \
60    for (int y = 0; y < bitmap.height(); ++y) \
61        for (int x = 0; x < bitmap.width(); ++x) {     \
62            int alpha = *bitmap.getAddr32(x, y) >> 24; \
63            bool opaque = opaqueRect.contains(x, y); \
64            EXPECT_EQ(opaque, alpha == 255); \
65        } \
66}
67
68TEST(GraphicsContextTest, trackOpaqueTest)
69{
70    SkBitmap bitmap;
71    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
72    bitmap.allocPixels();
73    bitmap.eraseColor(0);
74    SkCanvas canvas(bitmap);
75
76    GraphicsContext context(&canvas);
77    context.setTrackOpaqueRegion(true);
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.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
131    bitmap.allocPixels();
132    SkCanvas canvas(bitmap);
133
134    GraphicsContext context(&canvas);
135    context.setTrackOpaqueRegion(true);
136
137    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
138    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
139
140    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
141    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
142    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
143
144    context.clearRect(FloatRect(10, 10, 90, 90));
145    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
146
147    context.save();
148    context.clip(FloatRect(0, 0, 10, 10));
149    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
150    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
151    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
152    context.restore();
153
154    context.clearRect(FloatRect(10, 10, 90, 90));
155    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
156
157    context.save();
158    context.clip(FloatRect(20, 20, 10, 10));
159    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
160    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
161    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
162
163    context.clearRect(FloatRect(10, 10, 90, 90));
164    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
165
166    // The intersection of the two clips becomes empty.
167    context.clip(FloatRect(30, 20, 10, 10));
168    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
169    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
170    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
171    context.restore();
172
173    context.clearRect(FloatRect(10, 10, 90, 90));
174    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
175
176    // The transform and the clip need to interact correctly (transform first)
177    context.save();
178    context.translate(10, 10);
179    context.clip(FloatRect(20, 20, 10, 10));
180    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
181    EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), context.opaqueRegion().asRect());
182    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
183    context.restore();
184
185    context.clearRect(FloatRect(10, 10, 90, 90));
186    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
187
188    // The transform and the clip need to interact correctly (clip first)
189    context.save();
190    context.clip(FloatRect(20, 20, 10, 10));
191    context.translate(10, 10);
192    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
193    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
194    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
195    context.restore();
196
197    context.clearRect(FloatRect(10, 10, 90, 90));
198    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
199
200    Path path;
201    path.moveTo(FloatPoint(0, 0));
202    path.addLineTo(FloatPoint(100, 0));
203
204    // Non-rectangular clips just cause the paint to be considered non-opaque.
205    context.save();
206    context.clipPath(path, RULE_EVENODD);
207    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
208    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
209    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
210    context.restore();
211
212    // Another non-rectangular clip.
213    context.save();
214    context.clip(IntRect(30, 30, 20, 20));
215    context.clipOut(IntRect(30, 30, 10, 10));
216    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
217    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
218    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
219    context.restore();
220}
221
222TEST(GraphicsContextTest, trackImageMask)
223{
224    SkBitmap bitmap;
225    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
226    bitmap.allocPixels();
227    bitmap.eraseColor(0);
228    SkCanvas canvas(bitmap);
229
230    GraphicsContext context(&canvas);
231    context.setTrackOpaqueRegion(true);
232
233    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
234    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
235
236    // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
237    // out a transparency layer below that is filled with the mask color. In the end this should
238    // not be marked opaque.
239
240    context.setCompositeOperation(CompositeSourceOver);
241    context.beginTransparencyLayer(1);
242    context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
243
244    context.setCompositeOperation(CompositeDestinationIn);
245    context.beginTransparencyLayer(1);
246
247    OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
248    alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
249
250    context.setCompositeOperation(CompositeSourceOver);
251    context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
252
253    context.endLayer();
254    context.endLayer();
255
256    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
257    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
258}
259
260TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect)
261{
262    SkBitmap bitmap;
263    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
264    bitmap.allocPixels();
265    bitmap.eraseColor(0);
266    SkCanvas canvas(bitmap);
267
268    GraphicsContext context(&canvas);
269    context.setTrackOpaqueRegion(true);
270
271    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
272    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
273
274    // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
275    // out a transparency layer below that is filled with the mask color. In the end this should
276    // not be marked opaque.
277
278    context.setCompositeOperation(CompositeSourceOver);
279    context.beginTransparencyLayer(1);
280    context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
281
282    context.setCompositeOperation(CompositeDestinationIn);
283    context.beginTransparencyLayer(1);
284
285    OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
286    alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
287
288    context.setCompositeOperation(CompositeSourceOver);
289    context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
290
291    // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
292    context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver);
293
294    context.endLayer();
295    context.endLayer();
296
297    EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect());
298    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
299}
300
301TEST(GraphicsContextTest, trackOpaqueJoinTest)
302{
303    SkBitmap bitmap;
304    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
305    bitmap.allocPixels();
306    SkCanvas canvas(bitmap);
307
308    GraphicsContext context(&canvas);
309    context.setTrackOpaqueRegion(true);
310
311    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
312    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
313
314    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
315    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
316    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
317
318    // Doesn't join
319    context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver);
320    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
321    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
322
323    // Does join
324    context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver);
325    EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
326    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
327
328    // Doesn't join
329    context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver);
330    EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
331    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
332
333    // Does join
334    context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver);
335    EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
336    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
337
338    // Doesn't join
339    context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver);
340    EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
341    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
342
343    // Does join
344    context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver);
345    EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
346    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
347
348    // Doesn't join
349    context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver);
350    EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
351    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
352
353    // Does join
354    context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver);
355    EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect());
356    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
357}
358
359TEST(GraphicsContextTest, trackOpaqueLineTest)
360{
361    SkBitmap bitmap;
362    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
363    bitmap.allocPixels();
364    bitmap.eraseColor(0);
365    SkCanvas canvas(bitmap);
366
367    GraphicsContext context(&canvas);
368    context.setTrackOpaqueRegion(true);
369
370    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
371    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
372
373    context.setShouldAntialias(false);
374    context.setMiterLimit(0);
375    context.setStrokeThickness(4);
376    context.setLineCap(SquareCap);
377    context.setStrokeStyle(SolidStroke);
378    context.setCompositeOperation(CompositeSourceOver);
379
380    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
381    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
382    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
383
384    context.setCompositeOperation(CompositeSourceIn);
385
386    context.save();
387    context.setStrokeColor(alpha);
388    context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
389    context.restore();
390    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
391    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
392
393    context.save();
394    context.setStrokeColor(opaque);
395    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
396    context.restore();
397    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
398    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
399
400    context.save();
401    context.setStrokeColor(alpha);
402    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
403    context.restore();
404    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
405    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
406
407    context.save();
408    context.setStrokeColor(alpha);
409    context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
410    context.restore();
411    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
412    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
413
414    context.setShouldAntialias(true);
415    context.setCompositeOperation(CompositeSourceOver);
416
417    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
418    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
419    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
420
421    context.setCompositeOperation(CompositeSourceIn);
422
423    context.save();
424    context.setStrokeColor(alpha);
425    context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
426    context.restore();
427    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
428    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
429
430    context.setShouldAntialias(false);
431    context.save();
432    context.setStrokeColor(opaque);
433    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
434    context.restore();
435    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
436    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
437
438    context.setShouldAntialias(true);
439    context.save();
440    context.setStrokeColor(opaque);
441    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
442    context.restore();
443    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
444    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
445
446    context.save();
447    context.setStrokeColor(alpha);
448    context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
449    context.restore();
450    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
451    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
452}
453
454TEST(GraphicsContextTest, trackOpaquePathTest)
455{
456    SkBitmap bitmap;
457    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
458    bitmap.allocPixels();
459    SkCanvas canvas(bitmap);
460
461    GraphicsContext context(&canvas);
462    context.setTrackOpaqueRegion(true);
463
464    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
465    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
466
467    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
468    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
469    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
470
471    context.setShouldAntialias(false);
472    context.setMiterLimit(1);
473    context.setStrokeThickness(5);
474    context.setLineCap(SquareCap);
475    context.setStrokeStyle(SolidStroke);
476    context.setCompositeOperation(CompositeSourceIn);
477
478    Path path;
479
480    context.setFillColor(alpha);
481    path.moveTo(FloatPoint(0, 0));
482    path.addLineTo(FloatPoint(100, 0));
483    context.fillPath(path);
484    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
485    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
486    path.clear();
487
488    context.setFillColor(opaque);
489    path.moveTo(FloatPoint(0, 10));
490    path.addLineTo(FloatPoint(100, 13));
491    context.fillPath(path);
492    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
493    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
494    path.clear();
495
496    context.setFillColor(alpha);
497    path.moveTo(FloatPoint(0, 10));
498    path.addLineTo(FloatPoint(100, 13));
499    context.fillPath(path);
500    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
501    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
502    path.clear();
503
504    context.setFillColor(alpha);
505    path.moveTo(FloatPoint(0, 14));
506    path.addLineTo(FloatPoint(100, 10));
507    context.fillPath(path);
508    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
509    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
510    path.clear();
511}
512
513TEST(GraphicsContextTest, trackOpaqueImageTest)
514{
515    SkBitmap bitmap;
516    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
517    bitmap.allocPixels();
518    SkCanvas canvas(bitmap);
519
520    GraphicsContext context(&canvas);
521    context.setTrackOpaqueRegion(true);
522
523    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
524    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
525
526    SkBitmap opaqueBitmap;
527    opaqueBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kOpaque_SkAlphaType);
528    opaqueBitmap.allocPixels();
529
530    for (int y = 0; y < opaqueBitmap.height(); ++y)
531        for (int x = 0; x < opaqueBitmap.width(); ++x)
532            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
533    RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap));
534    EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque());
535
536    SkBitmap alphaBitmap;
537    alphaBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kPremul_SkAlphaType);
538    alphaBitmap.allocPixels();
539
540    for (int y = 0; y < alphaBitmap.height(); ++y)
541        for (int x = 0; x < alphaBitmap.width(); ++x)
542            *alphaBitmap.getAddr32(x, y) = 0x00000000;
543    RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap));
544    EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque());
545
546    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
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(0, 0));
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(0, 0));
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(5, 5));
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(5, 5));
561    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
562    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
563
564    context.drawImage(opaqueImage.get(), IntPoint(10, 10));
565    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
566    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
567    context.drawImage(alphaImage.get(), IntPoint(10, 10));
568    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
569    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
570
571    context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn);
572    EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect());
573    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
574
575    context.save();
576    context.setAlpha(0.5);
577    context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn);
578    context.restore();
579    EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect());
580    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
581
582    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
583    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
584    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
585
586    context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn);
587    EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect());
588    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
589
590    context.save();
591    context.setAlpha(0.5);
592    context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn);
593    context.restore();
594    EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect());
595    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
596}
597
598TEST(GraphicsContextTest, trackOpaqueOvalTest)
599{
600    SkBitmap bitmap;
601    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
602    bitmap.allocPixels();
603    bitmap.eraseColor(0);
604    SkCanvas canvas(bitmap);
605
606    GraphicsContext context(&canvas);
607    context.setTrackOpaqueRegion(true);
608
609    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
610    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
611
612    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
613    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
614
615    context.drawEllipse(IntRect(10, 10, 90, 90));
616    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
617    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
618
619    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
620    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
621    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
622
623    context.setCompositeOperation(CompositeSourceIn);
624
625    context.setShouldAntialias(false);
626
627    context.setFillColor(opaque);
628    context.drawEllipse(IntRect(10, 10, 50, 30));
629    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
630    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
631
632    context.setFillColor(alpha);
633    context.drawEllipse(IntRect(10, 10, 30, 50));
634    EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
635    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
636
637    context.setShouldAntialias(true);
638
639    context.setFillColor(opaque);
640    context.drawEllipse(IntRect(10, 10, 50, 30));
641    EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect());
642    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
643
644    context.setFillColor(alpha);
645    context.drawEllipse(IntRect(20, 10, 30, 50));
646    EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect());
647    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
648}
649
650TEST(GraphicsContextTest, trackOpaqueRoundedRectTest)
651{
652    SkBitmap bitmap;
653    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
654    bitmap.allocPixels();
655    bitmap.eraseColor(0);
656    SkCanvas canvas(bitmap);
657
658    GraphicsContext context(&canvas);
659    context.setTrackOpaqueRegion(true);
660
661    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
662    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
663    IntSize radii(10, 10);
664
665    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
666    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
667
668    context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque);
669    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
670    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
671
672    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
673    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
674    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
675
676    context.setCompositeOperation(CompositeSourceIn);
677    context.setShouldAntialias(false);
678
679    context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque);
680    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
681    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
682
683    context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha);
684    EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
685    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
686
687    context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha);
688    EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
689    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
690
691    context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque);
692    EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
693    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
694}
695
696TEST(GraphicsContextTest, trackOpaqueTextTest)
697{
698    int width = 200, height = 200;
699    SkBitmap bitmap;
700    bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
701    bitmap.allocPixels();
702    bitmap.eraseColor(0);
703    SkCanvas canvas(bitmap);
704    SkRect textRect = SkRect::MakeWH(width, height);
705
706    GraphicsContext context(&canvas);
707    context.setTrackOpaqueRegion(true);
708
709    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
710    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
711
712    SkPaint opaquePaint;
713    opaquePaint.setColor(opaque.rgb());
714    opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode);
715    SkPaint alphaPaint;
716    alphaPaint.setColor(alpha.rgb());
717    alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
718
719    SkPoint point = SkPoint::Make(0, 0);
720    SkScalar pointX = 0;
721    SkPath path;
722    path.moveTo(SkPoint::Make(0, 0));
723    path.lineTo(SkPoint::Make(100, 0));
724
725    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
726    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
727    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
728
729    context.drawPosText("A", 1, &point, textRect, opaquePaint);
730    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
731    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
732
733    context.drawPosText("A", 1, &point, textRect, alphaPaint);
734    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
735    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
736
737    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
738    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
739    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
740
741    context.drawPosTextH("A", 1, &pointX, 0, textRect, opaquePaint);
742    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
743    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
744
745    context.drawPosTextH("A", 1, &pointX, 0, textRect, alphaPaint);
746    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
747    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
748
749    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
750    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
751    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
752
753    context.drawTextOnPath("A", 1, path, textRect, 0, opaquePaint);
754    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
755    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
756
757    context.drawTextOnPath("A", 1, path, textRect, 0, alphaPaint);
758    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
759    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
760}
761
762TEST(GraphicsContextTest, trackOpaqueWritePixelsTest)
763{
764    SkBitmap bitmap;
765    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
766    bitmap.allocPixels();
767    bitmap.eraseColor(0);
768    SkCanvas canvas(bitmap);
769
770    GraphicsContext context(&canvas);
771    context.setTrackOpaqueRegion(true);
772
773    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
774
775    SkBitmap opaqueBitmap;
776    opaqueBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kOpaque_SkAlphaType);
777    opaqueBitmap.allocPixels();
778    for (int y = 0; y < opaqueBitmap.height(); ++y)
779        for (int x = 0; x < opaqueBitmap.width(); ++x)
780            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
781
782    SkBitmap alphaBitmap;
783    alphaBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kPremul_SkAlphaType);
784    alphaBitmap.allocPixels();
785    for (int y = 0; y < alphaBitmap.height(); ++y)
786        for (int x = 0; x < alphaBitmap.width(); ++x)
787            *alphaBitmap.getAddr32(x, y) = 0x00000000;
788
789    SkPaint paint;
790    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
791
792    context.writePixels(opaqueBitmap, 50, 50);
793    EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect());
794    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
795
796    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
797    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
798    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
799
800    context.writePixels(alphaBitmap, 10, 0);
801    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
802    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
803
804    context.writePixels(alphaBitmap, 10, 1);
805    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
806    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
807
808    context.writePixels(alphaBitmap, 0, 10);
809    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
810    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
811
812    context.writePixels(alphaBitmap, 1, 10);
813    EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
814    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
815}
816
817TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest)
818{
819    SkBitmap bitmap;
820    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
821    bitmap.allocPixels();
822    bitmap.eraseColor(0);
823    SkCanvas canvas(bitmap);
824
825    GraphicsContext context(&canvas);
826    context.setTrackOpaqueRegion(true);
827
828    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
829
830    SkBitmap opaqueBitmap;
831    opaqueBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kOpaque_SkAlphaType);
832    opaqueBitmap.allocPixels();
833    for (int y = 0; y < opaqueBitmap.height(); ++y)
834        for (int x = 0; x < opaqueBitmap.width(); ++x)
835            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
836
837    SkBitmap alphaBitmap;
838    alphaBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kPremul_SkAlphaType);
839    alphaBitmap.allocPixels();
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
872TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest)
873{
874    SkBitmap bitmap;
875    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 200, 200);
876    bitmap.allocPixels();
877    bitmap.eraseColor(0);
878    SkCanvas canvas(bitmap);
879
880    GraphicsContext context(&canvas);
881    context.setTrackOpaqueRegion(true);
882
883    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
884
885    SkBitmap opaqueBitmap;
886    opaqueBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kOpaque_SkAlphaType);
887    opaqueBitmap.allocPixels();
888    for (int y = 0; y < opaqueBitmap.height(); ++y)
889        for (int x = 0; x < opaqueBitmap.width(); ++x)
890            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
891
892    SkBitmap alphaBitmap;
893    alphaBitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10, 0, kPremul_SkAlphaType);
894    alphaBitmap.allocPixels();
895    for (int y = 0; y < alphaBitmap.height(); ++y)
896        for (int x = 0; x < alphaBitmap.width(); ++x)
897            *alphaBitmap.getAddr32(x, y) = 0x00000000;
898
899    SkPaint paint;
900    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
901
902    context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint);
903    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
904    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
905
906    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint);
907    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
908    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
909
910    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint);
911    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
912    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
913
914    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint);
915    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
916    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
917
918    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint);
919    EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
920    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
921}
922
923TEST(GraphicsContextTest, contextTransparencyLayerTest)
924{
925    SkBitmap bitmap;
926    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
927    bitmap.allocPixels();
928    bitmap.eraseColor(0);
929    SkCanvas canvas(bitmap);
930
931    GraphicsContext context(&canvas);
932    context.setTrackOpaqueRegion(true);
933
934    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
935    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
936    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
937    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
938
939    context.clearRect(FloatRect(20, 20, 10, 10));
940    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
941
942    context.beginTransparencyLayer(0.5);
943    context.save();
944    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
945    context.restore();
946    context.endLayer();
947    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
948
949    context.clearRect(FloatRect(20, 20, 10, 10));
950    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
951
952    context.beginTransparencyLayer(0.5);
953    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
954    context.endLayer();
955    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
956}
957
958TEST(GraphicsContextTest, UnboundedDrawsAreClipped)
959{
960    SkBitmap bitmap;
961    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
962    bitmap.allocPixels();
963    bitmap.eraseColor(0);
964    SkCanvas canvas(bitmap);
965
966    GraphicsContext context(&canvas);
967    context.setTrackOpaqueRegion(true);
968
969    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
970    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
971
972    Path path;
973    context.setShouldAntialias(false);
974    context.setMiterLimit(1);
975    context.setStrokeThickness(5);
976    context.setLineCap(SquareCap);
977    context.setStrokeStyle(SolidStroke);
978
979    // Make skia unable to compute fast bounds for our paths.
980    DashArray dashArray;
981    dashArray.append(1);
982    dashArray.append(0);
983    context.setLineDash(dashArray, 0);
984
985    // Make the device opaque in 10,10 40x40.
986    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
987    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
988    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
989
990    // Clip to the left edge of the opaque area.
991    context.clip(IntRect(10, 10, 10, 40));
992
993    // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
994    context.setCompositeOperation(CompositeSourceOut);
995    context.setFillColor(alpha);
996    path.moveTo(FloatPoint(10, 10));
997    path.addLineTo(FloatPoint(40, 40));
998    context.strokePath(path);
999
1000    EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect());
1001    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
1002}
1003
1004TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer)
1005{
1006    SkBitmap bitmap;
1007    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
1008    bitmap.allocPixels();
1009    bitmap.eraseColor(0);
1010    SkCanvas canvas(bitmap);
1011
1012    GraphicsContext context(&canvas);
1013    context.setTrackOpaqueRegion(true);
1014
1015    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1016    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
1017
1018    Path path;
1019    context.setShouldAntialias(false);
1020    context.setMiterLimit(1);
1021    context.setStrokeThickness(5);
1022    context.setLineCap(SquareCap);
1023    context.setStrokeStyle(SolidStroke);
1024
1025    // Make skia unable to compute fast bounds for our paths.
1026    DashArray dashArray;
1027    dashArray.append(1);
1028    dashArray.append(0);
1029    context.setLineDash(dashArray, 0);
1030
1031    // Make the device opaque in 10,10 40x40.
1032    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1033    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
1034    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1035
1036    // Begin a layer that preserves opaque.
1037    context.setCompositeOperation(CompositeSourceOver);
1038    context.beginTransparencyLayer(0.5);
1039
1040    // Begin a layer that does not preserve opaque.
1041    context.setCompositeOperation(CompositeSourceOut);
1042    context.beginTransparencyLayer(0.5);
1043
1044    // This should not destroy the device opaqueness.
1045    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1046
1047    // This should not destroy the device opaqueness either.
1048    context.setFillColor(opaque);
1049    path.moveTo(FloatPoint(10, 10));
1050    path.addLineTo(FloatPoint(40, 40));
1051    context.strokePath(path);
1052
1053    context.endLayer();
1054    context.endLayer();
1055    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
1056    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1057
1058    // Now begin a layer that does not preserve opaque and draw through it to the device.
1059    context.setCompositeOperation(CompositeSourceOut);
1060    context.beginTransparencyLayer(0.5);
1061
1062    // This should destroy the device opaqueness.
1063    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1064
1065    context.endLayer();
1066    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1067    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1068
1069    // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
1070
1071    context.setCompositeOperation(CompositeSourceOut);
1072    context.beginTransparencyLayer(0.5);
1073
1074    // This should nuke the device opaqueness.
1075    context.setFillColor(opaque);
1076    path.moveTo(FloatPoint(10, 10));
1077    path.addLineTo(FloatPoint(40, 40));
1078    context.strokePath(path);
1079
1080    context.endLayer();
1081    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1082    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1083}
1084
1085#define DISPATCH(c1, c2, op, params) do { c1.op(params); c2.op(params); } while (0);
1086
1087TEST(GraphicsContextTest, RecordingTotalMatrix)
1088{
1089    SkBitmap bitmap;
1090    bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
1091    bitmap.allocPixels();
1092    bitmap.eraseColor(0);
1093    SkCanvas canvas(bitmap);
1094    GraphicsContext context(&canvas);
1095
1096    SkBitmapDevice controlDevice(SkBitmap::kNo_Config, 400, 400);
1097    SkCanvas controlCanvas(&controlDevice);
1098    GraphicsContext controlContext(&controlCanvas);
1099
1100    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1101    DISPATCH(context, controlContext, scale, FloatSize(2, 2));
1102    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1103
1104    controlContext.save();
1105    context.beginRecording(FloatRect(0, 0, 200, 200));
1106    DISPATCH(context, controlContext, translate, FloatSize(10, 10));
1107    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1108
1109    controlContext.save();
1110    context.beginRecording(FloatRect(10, 10, 100, 100));
1111    DISPATCH(context, controlContext, rotate, 45);
1112    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1113
1114    controlContext.restore();
1115    context.endRecording();
1116    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1117
1118    controlContext.restore();
1119    context.endRecording();
1120    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1121}
1122
1123} // namespace
1124