Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / skia / ext / analysis_canvas_unittest.cc
blob5436b8130c96733c92d91545ac9a13f9d691473f
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/compiler_specific.h"
6 #include "skia/ext/analysis_canvas.h"
7 #include "skia/ext/refptr.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/skia/include/core/SkPicture.h"
10 #include "third_party/skia/include/core/SkPictureRecorder.h"
11 #include "third_party/skia/include/core/SkShader.h"
12 #include "third_party/skia/include/effects/SkOffsetImageFilter.h"
14 namespace {
16 void SolidColorFill(skia::AnalysisCanvas& canvas) {
17 canvas.clear(SkColorSetARGB(255, 255, 255, 255));
20 void TransparentFill(skia::AnalysisCanvas& canvas) {
21 canvas.clear(SkColorSetARGB(0, 0, 0, 0));
24 } // namespace
25 namespace skia {
27 TEST(AnalysisCanvasTest, EmptyCanvas) {
28 skia::AnalysisCanvas canvas(255, 255);
30 SkColor color;
31 EXPECT_TRUE(canvas.GetColorIfSolid(&color));
32 EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0));
35 TEST(AnalysisCanvasTest, ClearCanvas) {
36 skia::AnalysisCanvas canvas(255, 255);
38 // Transparent color
39 SkColor color = SkColorSetARGB(0, 12, 34, 56);
40 canvas.clear(color);
42 SkColor outputColor;
43 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
44 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
46 // Solid color
47 color = SkColorSetARGB(255, 65, 43, 21);
48 canvas.clear(color);
50 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
51 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
52 EXPECT_EQ(outputColor, color);
54 // Translucent color
55 color = SkColorSetARGB(128, 11, 22, 33);
56 canvas.clear(color);
58 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
60 // Test helper methods
61 SolidColorFill(canvas);
62 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
63 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
65 TransparentFill(canvas);
66 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
67 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
70 TEST(AnalysisCanvasTest, ComplexActions) {
71 skia::AnalysisCanvas canvas(255, 255);
73 // Draw paint test.
74 SkColor color = SkColorSetARGB(255, 11, 22, 33);
75 SkPaint paint;
76 paint.setColor(color);
78 canvas.drawPaint(paint);
80 SkColor outputColor;
81 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
83 // Draw points test.
84 SkPoint points[4] = {
85 SkPoint::Make(0, 0),
86 SkPoint::Make(255, 0),
87 SkPoint::Make(255, 255),
88 SkPoint::Make(0, 255)
91 SolidColorFill(canvas);
92 canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint);
94 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
96 // Draw oval test.
97 SolidColorFill(canvas);
98 canvas.drawOval(SkRect::MakeWH(255, 255), paint);
100 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
102 // Draw bitmap test.
103 SolidColorFill(canvas);
104 SkBitmap secondBitmap;
105 secondBitmap.allocN32Pixels(255, 255);
106 canvas.drawBitmap(secondBitmap, 0, 0);
108 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
111 TEST(AnalysisCanvasTest, SimpleDrawRect) {
112 skia::AnalysisCanvas canvas(255, 255);
114 SkColor color = SkColorSetARGB(255, 11, 22, 33);
115 SkPaint paint;
116 paint.setColor(color);
117 canvas.clipRect(SkRect::MakeWH(255, 255));
118 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
120 SkColor outputColor;
121 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
122 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
123 EXPECT_EQ(color, outputColor);
125 color = SkColorSetARGB(255, 22, 33, 44);
126 paint.setColor(color);
127 canvas.translate(-128, -128);
128 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
130 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
132 color = SkColorSetARGB(255, 33, 44, 55);
133 paint.setColor(color);
134 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
136 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
137 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
138 EXPECT_EQ(color, outputColor);
140 color = SkColorSetARGB(0, 0, 0, 0);
141 paint.setColor(color);
142 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
144 // This test relies on canvas treating a paint with 0-color as a no-op
145 // thus not changing its "is_solid" status.
146 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
147 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
148 EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55));
150 color = SkColorSetARGB(128, 128, 128, 128);
151 paint.setColor(color);
152 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
154 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
156 paint.setXfermodeMode(SkXfermode::kClear_Mode);
157 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
159 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
161 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
163 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
164 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
166 canvas.translate(128, 128);
167 color = SkColorSetARGB(255, 11, 22, 33);
168 paint.setColor(color);
169 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
170 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
172 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
173 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
174 EXPECT_EQ(color, outputColor);
176 canvas.rotate(50);
177 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
179 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
182 TEST(AnalysisCanvasTest, FilterPaint) {
183 skia::AnalysisCanvas canvas(255, 255);
184 SkPaint paint;
186 skia::RefPtr<SkImageFilter> filter =
187 skia::AdoptRef(SkOffsetImageFilter::Create(10, 10));
188 paint.setImageFilter(filter.get());
189 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
191 SkColor outputColor;
192 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
195 TEST(AnalysisCanvasTest, ClipPath) {
196 skia::AnalysisCanvas canvas(255, 255);
198 // Skia will look for paths that are actually rects and treat
199 // them as such. We add a divot to the following path to prevent
200 // this optimization and truly test clipPath's behavior.
201 SkPath path;
202 path.moveTo(0, 0);
203 path.lineTo(128, 50);
204 path.lineTo(255, 0);
205 path.lineTo(255, 255);
206 path.lineTo(0, 255);
208 SkColor outputColor;
209 SolidColorFill(canvas);
210 canvas.clipPath(path);
211 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
213 canvas.save();
214 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
216 canvas.clipPath(path);
217 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
219 canvas.restore();
220 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
222 SolidColorFill(canvas);
223 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
226 TEST(AnalysisCanvasTest, SaveLayerWithXfermode) {
227 skia::AnalysisCanvas canvas(255, 255);
228 SkRect bounds = SkRect::MakeWH(255, 255);
229 SkColor outputColor;
231 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
232 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
233 SkPaint paint;
235 // Note: nothing is draw to the the save layer, but solid color
236 // and transparency are handled conservatively in case the layer's
237 // SkPaint draws something. For example, there could be an
238 // SkPictureImageFilter. If someday analysis_canvas starts doing
239 // a deeper analysis of the SkPaint, this test may need to be
240 // redesigned.
241 TransparentFill(canvas);
242 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
243 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
244 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
245 canvas.saveLayer(&bounds, &paint);
246 canvas.restore();
247 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
249 TransparentFill(canvas);
250 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
251 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
252 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
253 canvas.saveLayer(&bounds, &paint);
254 canvas.restore();
255 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
257 // Layer with dst xfermode is a no-op, so this is the only case
258 // where solid color is unaffected by the layer.
259 TransparentFill(canvas);
260 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
261 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
262 paint.setXfermodeMode(SkXfermode::kDst_Mode);
263 canvas.saveLayer(&bounds, &paint);
264 canvas.restore();
265 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
266 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
269 TEST(AnalysisCanvasTest, SaveLayerRestore) {
270 skia::AnalysisCanvas canvas(255, 255);
272 SkColor outputColor;
273 SolidColorFill(canvas);
274 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
276 SkRect bounds = SkRect::MakeWH(255, 255);
277 SkPaint paint;
278 paint.setColor(SkColorSetARGB(255, 255, 255, 255));
279 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
281 // This should force non-transparency
282 canvas.saveLayer(&bounds, &paint);
283 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
284 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
286 TransparentFill(canvas);
287 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
289 SolidColorFill(canvas);
290 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
291 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
293 paint.setXfermodeMode(SkXfermode::kDst_Mode);
295 // This should force non-solid color
296 canvas.saveLayer(&bounds, &paint);
297 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
299 TransparentFill(canvas);
300 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
302 SolidColorFill(canvas);
303 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
305 canvas.restore();
306 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
308 TransparentFill(canvas);
309 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
311 SolidColorFill(canvas);
312 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
313 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
315 canvas.restore();
316 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
317 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
319 TransparentFill(canvas);
320 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
321 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
323 SolidColorFill(canvas);
324 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
325 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
328 TEST(AnalysisCanvasTest, EarlyOutNotSolid) {
329 SkRTreeFactory factory;
330 SkPictureRecorder recorder;
332 // Create a picture with 3 commands, last of which is non-solid.
333 skia::RefPtr<SkCanvas> record_canvas =
334 skia::SharePtr(recorder.beginRecording(256, 256, &factory));
336 std::string text = "text";
337 SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
339 SkPaint paint;
340 paint.setColor(SkColorSetARGB(255, 255, 255, 255));
341 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
343 record_canvas->drawRect(SkRect::MakeWH(256, 256), paint);
344 record_canvas->drawRect(SkRect::MakeWH(256, 256), paint);
345 record_canvas->drawText(
346 text.c_str(), text.length(), point.fX, point.fY, paint);
348 skia::RefPtr<SkPicture> picture =
349 skia::AdoptRef(recorder.endRecordingAsPicture());
351 // Draw the picture into the analysis canvas, using the canvas as a callback
352 // as well.
353 skia::AnalysisCanvas canvas(256, 256);
354 picture->playback(&canvas, &canvas);
356 // Ensure that canvas is not solid.
357 SkColor output_color;
358 EXPECT_FALSE(canvas.GetColorIfSolid(&output_color));
360 // Verify that we aborted drawing.
361 EXPECT_TRUE(canvas.abort());
364 TEST(AnalysisCanvasTest, ClipComplexRegion) {
365 skia::AnalysisCanvas canvas(255, 255);
367 SkPath path;
368 path.moveTo(0, 0);
369 path.lineTo(128, 50);
370 path.lineTo(255, 0);
371 path.lineTo(255, 255);
372 path.lineTo(0, 255);
373 SkIRect pathBounds = path.getBounds().round();
374 SkRegion region;
375 region.setPath(path, SkRegion(pathBounds));
377 SkColor outputColor;
378 SolidColorFill(canvas);
379 canvas.clipRegion(region);
380 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
382 canvas.save();
383 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
385 canvas.clipRegion(region);
386 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
388 canvas.restore();
389 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
391 SolidColorFill(canvas);
392 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
395 } // namespace skia