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 12namespace { 13 14void SolidColorFill(skia::AnalysisCanvas& canvas) { 15 canvas.clear(SkColorSetARGB(255, 255, 255, 255)); 16} 17 18void TransparentFill(skia::AnalysisCanvas& canvas) { 19 canvas.clear(SkColorSetARGB(0, 0, 0, 0)); 20} 21 22} // namespace 23namespace skia { 24 25TEST(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 33TEST(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 68TEST(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 110TEST(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 181TEST(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 193TEST(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 224TEST(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 283TEST(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