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.
4
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"
11
12 namespace {
13
SolidColorFill(skia::AnalysisCanvas & canvas)14 void SolidColorFill(skia::AnalysisCanvas& canvas) {
15 canvas.clear(SkColorSetARGB(255, 255, 255, 255));
16 }
17
TransparentFill(skia::AnalysisCanvas & canvas)18 void TransparentFill(skia::AnalysisCanvas& canvas) {
19 canvas.clear(SkColorSetARGB(0, 0, 0, 0));
20 }
21
22 } // namespace
23 namespace skia {
24
TEST(AnalysisCanvasTest,EmptyCanvas)25 TEST(AnalysisCanvasTest, EmptyCanvas) {
26 skia::AnalysisCanvas canvas(255, 255);
27
28 SkColor color;
29 EXPECT_TRUE(canvas.GetColorIfSolid(&color));
30 EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0));
31 }
32
TEST(AnalysisCanvasTest,ClearCanvas)33 TEST(AnalysisCanvasTest, ClearCanvas) {
34 skia::AnalysisCanvas canvas(255, 255);
35
36 // Transparent color
37 SkColor color = SkColorSetARGB(0, 12, 34, 56);
38 canvas.clear(color);
39
40 SkColor outputColor;
41 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
42 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
43
44 // Solid color
45 color = SkColorSetARGB(255, 65, 43, 21);
46 canvas.clear(color);
47
48 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
49 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
50 EXPECT_EQ(outputColor, color);
51
52 // Translucent color
53 color = SkColorSetARGB(128, 11, 22, 33);
54 canvas.clear(color);
55
56 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
57
58 // Test helper methods
59 SolidColorFill(canvas);
60 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
61 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
62
63 TransparentFill(canvas);
64 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
65 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
66 }
67
TEST(AnalysisCanvasTest,ComplexActions)68 TEST(AnalysisCanvasTest, ComplexActions) {
69 skia::AnalysisCanvas canvas(255, 255);
70
71 // Draw paint test.
72 SkColor color = SkColorSetARGB(255, 11, 22, 33);
73 SkPaint paint;
74 paint.setColor(color);
75
76 canvas.drawPaint(paint);
77
78 SkColor outputColor;
79 //TODO(vmpstr): This should return true. (crbug.com/180597)
80 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
81
82 // Draw points test.
83 SkPoint points[4] = {
84 SkPoint::Make(0, 0),
85 SkPoint::Make(255, 0),
86 SkPoint::Make(255, 255),
87 SkPoint::Make(0, 255)
88 };
89
90 SolidColorFill(canvas);
91 canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint);
92
93 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
94
95 // Draw oval test.
96 SolidColorFill(canvas);
97 canvas.drawOval(SkRect::MakeWH(255, 255), paint);
98
99 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
100
101 // Draw bitmap test.
102 SolidColorFill(canvas);
103 SkBitmap secondBitmap;
104 secondBitmap.allocN32Pixels(255, 255);
105 canvas.drawBitmap(secondBitmap, 0, 0);
106
107 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
108 }
109
TEST(AnalysisCanvasTest,SimpleDrawRect)110 TEST(AnalysisCanvasTest, SimpleDrawRect) {
111 skia::AnalysisCanvas canvas(255, 255);
112
113 SkColor color = SkColorSetARGB(255, 11, 22, 33);
114 SkPaint paint;
115 paint.setColor(color);
116 canvas.clipRect(SkRect::MakeWH(255, 255));
117 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
118
119 SkColor outputColor;
120 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
121 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
122 EXPECT_EQ(color, outputColor);
123
124 color = SkColorSetARGB(255, 22, 33, 44);
125 paint.setColor(color);
126 canvas.translate(-128, -128);
127 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
128
129 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
130
131 color = SkColorSetARGB(255, 33, 44, 55);
132 paint.setColor(color);
133 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
134
135 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
136 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
137 EXPECT_EQ(color, outputColor);
138
139 color = SkColorSetARGB(0, 0, 0, 0);
140 paint.setColor(color);
141 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
142
143 // This test relies on canvas treating a paint with 0-color as a no-op
144 // thus not changing its "is_solid" status.
145 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
146 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
147 EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55));
148
149 color = SkColorSetARGB(128, 128, 128, 128);
150 paint.setColor(color);
151 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
152
153 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
154
155 paint.setXfermodeMode(SkXfermode::kClear_Mode);
156 canvas.drawRect(SkRect::MakeWH(382, 382), paint);
157
158 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
159
160 canvas.drawRect(SkRect::MakeWH(383, 383), paint);
161
162 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
163 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
164
165 canvas.translate(128, 128);
166 color = SkColorSetARGB(255, 11, 22, 33);
167 paint.setColor(color);
168 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
169 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
170
171 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
172 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
173 EXPECT_EQ(color, outputColor);
174
175 canvas.rotate(50);
176 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
177
178 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
179 }
180
TEST(AnalysisCanvasTest,FilterPaint)181 TEST(AnalysisCanvasTest, FilterPaint) {
182 skia::AnalysisCanvas canvas(255, 255);
183 SkPaint paint;
184
185 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkOffsetImageFilter::Create(10, 10));
186 paint.setImageFilter(filter.get());
187 canvas.drawRect(SkRect::MakeWH(255, 255), paint);
188
189 SkColor outputColor;
190 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
191 }
192
TEST(AnalysisCanvasTest,ClipPath)193 TEST(AnalysisCanvasTest, ClipPath) {
194 skia::AnalysisCanvas canvas(255, 255);
195
196 // Skia will look for paths that are actually rects and treat
197 // them as such. We add a divot to the following path to prevent
198 // this optimization and truly test clipPath's behavior.
199 SkPath path;
200 path.moveTo(0, 0);
201 path.lineTo(128, 50);
202 path.lineTo(255, 0);
203 path.lineTo(255, 255);
204 path.lineTo(0, 255);
205
206 SkColor outputColor;
207 SolidColorFill(canvas);
208 canvas.clipPath(path);
209 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
210
211 canvas.save();
212 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
213
214 canvas.clipPath(path);
215 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
216
217 canvas.restore();
218 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
219
220 SolidColorFill(canvas);
221 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
222 }
223
TEST(AnalysisCanvasTest,SaveLayerRestore)224 TEST(AnalysisCanvasTest, SaveLayerRestore) {
225 skia::AnalysisCanvas canvas(255, 255);
226
227 SkColor outputColor;
228 SolidColorFill(canvas);
229 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
230
231 SkRect bounds = SkRect::MakeWH(255, 255);
232 SkPaint paint;
233 paint.setColor(SkColorSetARGB(255, 255, 255, 255));
234 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
235
236 // This should force non-transparency
237 canvas.saveLayer(&bounds, &paint);
238 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
239 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
240
241 TransparentFill(canvas);
242 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
243
244 SolidColorFill(canvas);
245 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
246 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
247
248 paint.setXfermodeMode(SkXfermode::kDst_Mode);
249
250 // This should force non-solid color
251 canvas.saveLayer(&bounds, &paint);
252 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
253
254 TransparentFill(canvas);
255 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
256
257 SolidColorFill(canvas);
258 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
259
260 canvas.restore();
261 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
262
263 TransparentFill(canvas);
264 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
265
266 SolidColorFill(canvas);
267 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
268 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
269
270 canvas.restore();
271 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
272 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
273
274 TransparentFill(canvas);
275 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
276 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
277
278 SolidColorFill(canvas);
279 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
280 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
281 }
282
TEST(AnalysisCanvasTest,HasText)283 TEST(AnalysisCanvasTest, HasText) {
284 int width = 200;
285 int height = 100;
286
287 const char* text = "A";
288 size_t byteLength = 1;
289
290 SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25));
291 SkPath path;
292 path.moveTo(point);
293 path.lineTo(SkIntToScalar(75), SkIntToScalar(75));
294
295 SkPaint paint;
296 paint.setColor(SK_ColorGRAY);
297 paint.setTextSize(SkIntToScalar(10));
298
299 {
300 skia::AnalysisCanvas canvas(width, height);
301 // Test after initialization.
302 EXPECT_FALSE(canvas.HasText());
303 // Test drawing anything other than text.
304 canvas.drawRect(SkRect::MakeWH(width/2, height), paint);
305 EXPECT_FALSE(canvas.HasText());
306 }
307 {
308 // Test SkCanvas::drawText.
309 skia::AnalysisCanvas canvas(width, height);
310 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
311 EXPECT_TRUE(canvas.HasText());
312 }
313 {
314 // Test SkCanvas::drawPosText.
315 skia::AnalysisCanvas canvas(width, height);
316 canvas.drawPosText(text, byteLength, &point, paint);
317 EXPECT_TRUE(canvas.HasText());
318 }
319 {
320 // Test SkCanvas::drawPosTextH.
321 skia::AnalysisCanvas canvas(width, height);
322 canvas.drawPosTextH(text, byteLength, &point.fX, point.fY, paint);
323 EXPECT_TRUE(canvas.HasText());
324 }
325 {
326 // Test SkCanvas::drawTextOnPathHV.
327 skia::AnalysisCanvas canvas(width, height);
328 canvas.drawTextOnPathHV(text, byteLength, path, point.fX, point.fY, paint);
329 EXPECT_TRUE(canvas.HasText());
330 }
331 {
332 // Test SkCanvas::drawTextOnPath.
333 skia::AnalysisCanvas canvas(width, height);
334 canvas.drawTextOnPath(text, byteLength, path, NULL, paint);
335 EXPECT_TRUE(canvas.HasText());
336 }
337 {
338 // Text under opaque rect.
339 skia::AnalysisCanvas canvas(width, height);
340 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
341 EXPECT_TRUE(canvas.HasText());
342 canvas.drawRect(SkRect::MakeWH(width, height), paint);
343 EXPECT_FALSE(canvas.HasText());
344 }
345 {
346 // Text under translucent rect.
347 skia::AnalysisCanvas canvas(width, height);
348 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
349 EXPECT_TRUE(canvas.HasText());
350 SkPaint translucentPaint;
351 translucentPaint.setColor(0x88FFFFFF);
352 canvas.drawRect(SkRect::MakeWH(width, height), translucentPaint);
353 EXPECT_TRUE(canvas.HasText());
354 }
355 {
356 // Text under rect in clear mode.
357 skia::AnalysisCanvas canvas(width, height);
358 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
359 EXPECT_TRUE(canvas.HasText());
360 SkPaint clearModePaint;
361 clearModePaint.setXfermodeMode(SkXfermode::kClear_Mode);
362 canvas.drawRect(SkRect::MakeWH(width, height), clearModePaint);
363 EXPECT_FALSE(canvas.HasText());
364 }
365 {
366 // Clear.
367 skia::AnalysisCanvas canvas(width, height);
368 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
369 EXPECT_TRUE(canvas.HasText());
370 canvas.clear(SK_ColorGRAY);
371 EXPECT_FALSE(canvas.HasText());
372 }
373 {
374 // Text inside clip region.
375 skia::AnalysisCanvas canvas(width, height);
376 canvas.clipRect(SkRect::MakeWH(100, 100));
377 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
378 EXPECT_TRUE(canvas.HasText());
379 }
380 {
381 // Text outside clip region.
382 skia::AnalysisCanvas canvas(width, height);
383 canvas.clipRect(SkRect::MakeXYWH(100, 0, 100, 100));
384 canvas.drawText(text, byteLength, point.fX, point.fY, paint);
385 // Analysis device does not do any clipping.
386 // So even when text is outside the clip region,
387 // it is marked as having the text.
388 // TODO(alokp): We may be able to do some trivial rejection.
389 EXPECT_TRUE(canvas.HasText());
390 }
391 }
392
393 } // namespace skia
394