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/SkShader.h"
10 #include "third_party/skia/include/effects/SkOffsetImageFilter.h"
14 void SolidColorFill(skia::AnalysisCanvas
& canvas
) {
15 canvas
.clear(SkColorSetARGB(255, 255, 255, 255));
18 void TransparentFill(skia::AnalysisCanvas
& canvas
) {
19 canvas
.clear(SkColorSetARGB(0, 0, 0, 0));
25 TEST(AnalysisCanvasTest
, EmptyCanvas
) {
26 skia::AnalysisCanvas
canvas(255, 255);
29 EXPECT_TRUE(canvas
.GetColorIfSolid(&color
));
30 EXPECT_EQ(color
, SkColorSetARGB(0, 0, 0, 0));
33 TEST(AnalysisCanvasTest
, ClearCanvas
) {
34 skia::AnalysisCanvas
canvas(255, 255);
37 SkColor color
= SkColorSetARGB(0, 12, 34, 56);
41 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
42 EXPECT_EQ(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
45 color
= SkColorSetARGB(255, 65, 43, 21);
48 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
49 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
50 EXPECT_EQ(outputColor
, color
);
53 color
= SkColorSetARGB(128, 11, 22, 33);
56 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
58 // Test helper methods
59 SolidColorFill(canvas
);
60 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
61 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
63 TransparentFill(canvas
);
64 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
65 EXPECT_EQ(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
68 TEST(AnalysisCanvasTest
, ComplexActions
) {
69 skia::AnalysisCanvas
canvas(255, 255);
72 SkColor color
= SkColorSetARGB(255, 11, 22, 33);
74 paint
.setColor(color
);
76 canvas
.drawPaint(paint
);
79 //TODO(vmpstr): This should return true. (crbug.com/180597)
80 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
85 SkPoint::Make(255, 0),
86 SkPoint::Make(255, 255),
90 SolidColorFill(canvas
);
91 canvas
.drawPoints(SkCanvas::kLines_PointMode
, 4, points
, paint
);
93 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
96 SolidColorFill(canvas
);
97 canvas
.drawOval(SkRect::MakeWH(255, 255), paint
);
99 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
102 SolidColorFill(canvas
);
103 SkBitmap secondBitmap
;
104 secondBitmap
.setConfig(SkBitmap::kARGB_8888_Config
, 255, 255);
105 secondBitmap
.allocPixels();
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);
116 paint
.setColor(color
);
117 canvas
.clipRect(SkRect::MakeWH(255, 255));
118 canvas
.drawRect(SkRect::MakeWH(255, 255), paint
);
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
);
177 canvas
.drawRect(SkRect::MakeWH(255, 255), paint
);
179 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
182 TEST(AnalysisCanvasTest
, FilterPaint
) {
183 skia::AnalysisCanvas
canvas(255, 255);
186 skia::RefPtr
<SkImageFilter
> filter
= skia::AdoptRef(SkOffsetImageFilter::Create(10, 10));
187 paint
.setImageFilter(filter
.get());
188 canvas
.drawRect(SkRect::MakeWH(255, 255), paint
);
191 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
194 TEST(AnalysisCanvasTest
, ClipPath
) {
195 skia::AnalysisCanvas
canvas(255, 255);
197 // Skia will look for paths that are actually rects and treat
198 // them as such. We add a divot to the following path to prevent
199 // this optimization and truly test clipPath's behavior.
202 path
.lineTo(128, 50);
204 path
.lineTo(255, 255);
208 SolidColorFill(canvas
);
209 canvas
.clipPath(path
);
210 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
213 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
215 canvas
.clipPath(path
);
216 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
219 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
221 SolidColorFill(canvas
);
222 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
225 TEST(AnalysisCanvasTest
, SaveLayerRestore
) {
226 skia::AnalysisCanvas
canvas(255, 255);
229 SolidColorFill(canvas
);
230 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
232 SkRect bounds
= SkRect::MakeWH(255, 255);
234 paint
.setColor(SkColorSetARGB(255, 255, 255, 255));
235 paint
.setXfermodeMode(SkXfermode::kSrcOver_Mode
);
237 // This should force non-transparency
238 canvas
.saveLayer(&bounds
, &paint
);
239 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
240 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
242 TransparentFill(canvas
);
243 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
245 SolidColorFill(canvas
);
246 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
247 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
249 paint
.setXfermodeMode(SkXfermode::kDst_Mode
);
251 // This should force non-solid color
252 canvas
.saveLayer(&bounds
, &paint
);
253 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
255 TransparentFill(canvas
);
256 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
258 SolidColorFill(canvas
);
259 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
262 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
264 TransparentFill(canvas
);
265 EXPECT_FALSE(canvas
.GetColorIfSolid(&outputColor
));
267 SolidColorFill(canvas
);
268 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
269 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
272 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
273 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
275 TransparentFill(canvas
);
276 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
277 EXPECT_EQ(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
279 SolidColorFill(canvas
);
280 EXPECT_TRUE(canvas
.GetColorIfSolid(&outputColor
));
281 EXPECT_NE(static_cast<SkColor
>(SK_ColorTRANSPARENT
), outputColor
);
284 TEST(AnalysisCanvasTest
, HasText
) {
288 const char* text
= "A";
289 size_t byteLength
= 1;
291 SkPoint point
= SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
294 path
.lineTo(SkIntToScalar(75), SkIntToScalar(75));
297 paint
.setColor(SK_ColorGRAY
);
298 paint
.setTextSize(SkIntToScalar(10));
301 skia::AnalysisCanvas
canvas(width
, height
);
302 // Test after initialization.
303 EXPECT_FALSE(canvas
.HasText());
304 // Test drawing anything other than text.
305 canvas
.drawRect(SkRect::MakeWH(width
/2, height
), paint
);
306 EXPECT_FALSE(canvas
.HasText());
309 // Test SkCanvas::drawText.
310 skia::AnalysisCanvas
canvas(width
, height
);
311 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
312 EXPECT_TRUE(canvas
.HasText());
315 // Test SkCanvas::drawPosText.
316 skia::AnalysisCanvas
canvas(width
, height
);
317 canvas
.drawPosText(text
, byteLength
, &point
, paint
);
318 EXPECT_TRUE(canvas
.HasText());
321 // Test SkCanvas::drawPosTextH.
322 skia::AnalysisCanvas
canvas(width
, height
);
323 canvas
.drawPosTextH(text
, byteLength
, &point
.fX
, point
.fY
, paint
);
324 EXPECT_TRUE(canvas
.HasText());
327 // Test SkCanvas::drawTextOnPathHV.
328 skia::AnalysisCanvas
canvas(width
, height
);
329 canvas
.drawTextOnPathHV(text
, byteLength
, path
, point
.fX
, point
.fY
, paint
);
330 EXPECT_TRUE(canvas
.HasText());
333 // Test SkCanvas::drawTextOnPath.
334 skia::AnalysisCanvas
canvas(width
, height
);
335 canvas
.drawTextOnPath(text
, byteLength
, path
, NULL
, paint
);
336 EXPECT_TRUE(canvas
.HasText());
339 // Text under opaque rect.
340 skia::AnalysisCanvas
canvas(width
, height
);
341 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
342 EXPECT_TRUE(canvas
.HasText());
343 canvas
.drawRect(SkRect::MakeWH(width
, height
), paint
);
344 EXPECT_FALSE(canvas
.HasText());
347 // Text under translucent rect.
348 skia::AnalysisCanvas
canvas(width
, height
);
349 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
350 EXPECT_TRUE(canvas
.HasText());
351 SkPaint translucentPaint
;
352 translucentPaint
.setColor(0x88FFFFFF);
353 canvas
.drawRect(SkRect::MakeWH(width
, height
), translucentPaint
);
354 EXPECT_TRUE(canvas
.HasText());
357 // Text under rect in clear mode.
358 skia::AnalysisCanvas
canvas(width
, height
);
359 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
360 EXPECT_TRUE(canvas
.HasText());
361 SkPaint clearModePaint
;
362 clearModePaint
.setXfermodeMode(SkXfermode::kClear_Mode
);
363 canvas
.drawRect(SkRect::MakeWH(width
, height
), clearModePaint
);
364 EXPECT_FALSE(canvas
.HasText());
368 skia::AnalysisCanvas
canvas(width
, height
);
369 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
370 EXPECT_TRUE(canvas
.HasText());
371 canvas
.clear(SK_ColorGRAY
);
372 EXPECT_FALSE(canvas
.HasText());
375 // Text inside clip region.
376 skia::AnalysisCanvas
canvas(width
, height
);
377 canvas
.clipRect(SkRect::MakeWH(100, 100));
378 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
379 EXPECT_TRUE(canvas
.HasText());
382 // Text outside clip region.
383 skia::AnalysisCanvas
canvas(width
, height
);
384 canvas
.clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
385 canvas
.drawText(text
, byteLength
, point
.fX
, point
.fY
, paint
);
386 // Analysis device does not do any clipping.
387 // So even when text is outside the clip region,
388 // it is marked as having the text.
389 // TODO(alokp): We may be able to do some trivial rejection.
390 EXPECT_TRUE(canvas
.HasText());