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/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" 13 14namespace { 15 16void SolidColorFill(skia::AnalysisCanvas& canvas) { 17 canvas.clear(SkColorSetARGB(255, 255, 255, 255)); 18} 19 20void TransparentFill(skia::AnalysisCanvas& canvas) { 21 canvas.clear(SkColorSetARGB(0, 0, 0, 0)); 22} 23 24} // namespace 25namespace skia { 26 27TEST(AnalysisCanvasTest, EmptyCanvas) { 28 skia::AnalysisCanvas canvas(255, 255); 29 30 SkColor color; 31 EXPECT_TRUE(canvas.GetColorIfSolid(&color)); 32 EXPECT_EQ(color, SkColorSetARGB(0, 0, 0, 0)); 33} 34 35TEST(AnalysisCanvasTest, ClearCanvas) { 36 skia::AnalysisCanvas canvas(255, 255); 37 38 // Transparent color 39 SkColor color = SkColorSetARGB(0, 12, 34, 56); 40 canvas.clear(color); 41 42 SkColor outputColor; 43 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 44 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 45 46 // Solid color 47 color = SkColorSetARGB(255, 65, 43, 21); 48 canvas.clear(color); 49 50 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 51 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 52 EXPECT_EQ(outputColor, color); 53 54 // Translucent color 55 color = SkColorSetARGB(128, 11, 22, 33); 56 canvas.clear(color); 57 58 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 59 60 // Test helper methods 61 SolidColorFill(canvas); 62 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 63 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 64 65 TransparentFill(canvas); 66 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 67 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 68} 69 70TEST(AnalysisCanvasTest, ComplexActions) { 71 skia::AnalysisCanvas canvas(255, 255); 72 73 // Draw paint test. 74 SkColor color = SkColorSetARGB(255, 11, 22, 33); 75 SkPaint paint; 76 paint.setColor(color); 77 78 canvas.drawPaint(paint); 79 80 SkColor outputColor; 81 //TODO(vmpstr): This should return true. (crbug.com/180597) 82 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 83 84 // Draw points test. 85 SkPoint points[4] = { 86 SkPoint::Make(0, 0), 87 SkPoint::Make(255, 0), 88 SkPoint::Make(255, 255), 89 SkPoint::Make(0, 255) 90 }; 91 92 SolidColorFill(canvas); 93 canvas.drawPoints(SkCanvas::kLines_PointMode, 4, points, paint); 94 95 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 96 97 // Draw oval test. 98 SolidColorFill(canvas); 99 canvas.drawOval(SkRect::MakeWH(255, 255), paint); 100 101 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 102 103 // Draw bitmap test. 104 SolidColorFill(canvas); 105 SkBitmap secondBitmap; 106 secondBitmap.allocN32Pixels(255, 255); 107 canvas.drawBitmap(secondBitmap, 0, 0); 108 109 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 110} 111 112TEST(AnalysisCanvasTest, SimpleDrawRect) { 113 skia::AnalysisCanvas canvas(255, 255); 114 115 SkColor color = SkColorSetARGB(255, 11, 22, 33); 116 SkPaint paint; 117 paint.setColor(color); 118 canvas.clipRect(SkRect::MakeWH(255, 255)); 119 canvas.drawRect(SkRect::MakeWH(255, 255), paint); 120 121 SkColor outputColor; 122 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 123 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 124 EXPECT_EQ(color, outputColor); 125 126 color = SkColorSetARGB(255, 22, 33, 44); 127 paint.setColor(color); 128 canvas.translate(-128, -128); 129 canvas.drawRect(SkRect::MakeWH(382, 382), paint); 130 131 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 132 133 color = SkColorSetARGB(255, 33, 44, 55); 134 paint.setColor(color); 135 canvas.drawRect(SkRect::MakeWH(383, 383), paint); 136 137 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 138 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 139 EXPECT_EQ(color, outputColor); 140 141 color = SkColorSetARGB(0, 0, 0, 0); 142 paint.setColor(color); 143 canvas.drawRect(SkRect::MakeWH(383, 383), paint); 144 145 // This test relies on canvas treating a paint with 0-color as a no-op 146 // thus not changing its "is_solid" status. 147 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 148 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 149 EXPECT_EQ(outputColor, SkColorSetARGB(255, 33, 44, 55)); 150 151 color = SkColorSetARGB(128, 128, 128, 128); 152 paint.setColor(color); 153 canvas.drawRect(SkRect::MakeWH(383, 383), paint); 154 155 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 156 157 paint.setXfermodeMode(SkXfermode::kClear_Mode); 158 canvas.drawRect(SkRect::MakeWH(382, 382), paint); 159 160 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 161 162 canvas.drawRect(SkRect::MakeWH(383, 383), paint); 163 164 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 165 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 166 167 canvas.translate(128, 128); 168 color = SkColorSetARGB(255, 11, 22, 33); 169 paint.setColor(color); 170 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 171 canvas.drawRect(SkRect::MakeWH(255, 255), paint); 172 173 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 174 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 175 EXPECT_EQ(color, outputColor); 176 177 canvas.rotate(50); 178 canvas.drawRect(SkRect::MakeWH(255, 255), paint); 179 180 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 181} 182 183TEST(AnalysisCanvasTest, FilterPaint) { 184 skia::AnalysisCanvas canvas(255, 255); 185 SkPaint paint; 186 187 skia::RefPtr<SkImageFilter> filter = skia::AdoptRef(SkOffsetImageFilter::Create(10, 10)); 188 paint.setImageFilter(filter.get()); 189 canvas.drawRect(SkRect::MakeWH(255, 255), paint); 190 191 SkColor outputColor; 192 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 193} 194 195TEST(AnalysisCanvasTest, ClipPath) { 196 skia::AnalysisCanvas canvas(255, 255); 197 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); 207 208 SkColor outputColor; 209 SolidColorFill(canvas); 210 canvas.clipPath(path); 211 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 212 213 canvas.save(); 214 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 215 216 canvas.clipPath(path); 217 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 218 219 canvas.restore(); 220 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 221 222 SolidColorFill(canvas); 223 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 224} 225 226TEST(AnalysisCanvasTest, SaveLayerRestore) { 227 skia::AnalysisCanvas canvas(255, 255); 228 229 SkColor outputColor; 230 SolidColorFill(canvas); 231 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 232 233 SkRect bounds = SkRect::MakeWH(255, 255); 234 SkPaint paint; 235 paint.setColor(SkColorSetARGB(255, 255, 255, 255)); 236 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 237 238 // This should force non-transparency 239 canvas.saveLayer(&bounds, &paint); 240 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 241 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 242 243 TransparentFill(canvas); 244 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 245 246 SolidColorFill(canvas); 247 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 248 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 249 250 paint.setXfermodeMode(SkXfermode::kDst_Mode); 251 252 // This should force non-solid color 253 canvas.saveLayer(&bounds, &paint); 254 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 255 256 TransparentFill(canvas); 257 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 258 259 SolidColorFill(canvas); 260 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 261 262 canvas.restore(); 263 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 264 265 TransparentFill(canvas); 266 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 267 268 SolidColorFill(canvas); 269 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 270 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 271 272 canvas.restore(); 273 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 274 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 275 276 TransparentFill(canvas); 277 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 278 EXPECT_EQ(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 279 280 SolidColorFill(canvas); 281 EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor)); 282 EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor); 283} 284 285TEST(AnalysisCanvasTest, EarlyOutNotSolid) { 286 SkTileGridFactory::TileGridInfo tile_grid_info; 287 tile_grid_info.fTileInterval.set(256, 256); 288 tile_grid_info.fOffset.setZero(); 289 tile_grid_info.fMargin.setEmpty(); 290 SkTileGridFactory factory(tile_grid_info); 291 SkPictureRecorder recorder; 292 293 // Create a picture with 3 commands, last of which is non-solid. 294 skia::RefPtr<SkCanvas> record_canvas = 295 skia::SharePtr(recorder.beginRecording(256, 256, &factory)); 296 297 std::string text = "text"; 298 SkPoint point = SkPoint::Make(SkIntToScalar(25), SkIntToScalar(25)); 299 300 SkPaint paint; 301 paint.setColor(SkColorSetARGB(255, 255, 255, 255)); 302 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); 303 304 record_canvas->drawRect(SkRect::MakeWH(256, 256), paint); 305 record_canvas->drawRect(SkRect::MakeWH(256, 256), paint); 306 record_canvas->drawText( 307 text.c_str(), text.length(), point.fX, point.fY, paint); 308 309 skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); 310 311 // Draw the picture into the analysis canvas, using the canvas as a callback 312 // as well. 313 skia::AnalysisCanvas canvas(256, 256); 314 picture->draw(&canvas, &canvas); 315 316 // Ensure that canvas is not solid. 317 SkColor output_color; 318 EXPECT_FALSE(canvas.GetColorIfSolid(&output_color)); 319 320 // Verify that we aborted drawing. 321 EXPECT_TRUE(canvas.abortDrawing()); 322 323} 324 325TEST(AnalysisCanvasTest, ClipComplexRegion) { 326 skia::AnalysisCanvas canvas(255, 255); 327 328 SkPath path; 329 path.moveTo(0, 0); 330 path.lineTo(128, 50); 331 path.lineTo(255, 0); 332 path.lineTo(255, 255); 333 path.lineTo(0, 255); 334 SkIRect pathBounds = path.getBounds().round(); 335 SkRegion region; 336 region.setPath(path, SkRegion(pathBounds)); 337 338 SkColor outputColor; 339 SolidColorFill(canvas); 340 canvas.clipRegion(region); 341 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 342 343 canvas.save(); 344 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 345 346 canvas.clipRegion(region); 347 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 348 349 canvas.restore(); 350 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 351 352 SolidColorFill(canvas); 353 EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor)); 354} 355 356} // namespace skia 357