1 2 /* 3 * Copyright 2012 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 /* Description: 10 * This test defines a series of elementatry test steps that perform 11 * a single or a small group of canvas API calls. Each test step is 12 * used in several test cases that verify that different types of SkCanvas 13 * flavors and derivatives pass it and yield consistent behavior. The 14 * test cases analyse results that are queryable through the API. They do 15 * not look at rendering results. 16 * 17 * Adding test stepss: 18 * The general pattern for creating a new test step is to write a test 19 * function of the form: 20 * 21 * static void MyTestStepFunction(SkCanvas* canvas, 22 * skiatest::Reporter* reporter, 23 * CanvasTestStep* testStep) 24 * { 25 * canvas->someCanvasAPImethod(); 26 * (...) 27 * REPORTER_ASSERT_MESSAGE(reporter, (...), \ 28 * testStep->assertMessage()); 29 * } 30 * 31 * The definition of the test step function should be followed by an 32 * invocation of the TEST_STEP macro, which generates a class and 33 * instance for the test step: 34 * 35 * TEST_STEP(MyTestStep, MyTestStepFunction) 36 * 37 * There are also short hand macros for defining simple test steps 38 * in a single line of code. A simple test step is a one that is made 39 * of a single canvas API call. 40 * 41 * SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod()); 42 * 43 * There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that 44 * works the same way as SIMPLE_TEST_STEP, and additionally verifies 45 * that the invoked method returns a non-zero value. 46 */ 47 #include "SkBitmap.h" 48 #include "SkCanvas.h" 49 #include "SkDeferredCanvas.h" 50 #include "SkDevice.h" 51 #include "SkMatrix.h" 52 #include "SkNWayCanvas.h" 53 #include "SkPDFDevice.h" 54 #include "SkPDFDocument.h" 55 #include "SkPaint.h" 56 #include "SkPath.h" 57 #include "SkPicture.h" 58 #include "SkPictureRecord.h" 59 #include "SkProxyCanvas.h" 60 #include "SkRect.h" 61 #include "SkRegion.h" 62 #include "SkShader.h" 63 #include "SkStream.h" 64 #include "SkTDArray.h" 65 #include "Test.h" 66 67 class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor { 68 public: 69 Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {} 70 71 virtual void clipRect(const SkRect& r, SkRegion::Op op, bool aa) { 72 fTarget->clipRect(r, op, aa); 73 } 74 virtual void clipPath(const SkPath& p, SkRegion::Op op, bool aa) { 75 fTarget->clipPath(p, op, aa); 76 } 77 78 private: 79 SkCanvas* fTarget; 80 }; 81 82 static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) { 83 SkISize size = canvas->getDeviceSize(); 84 85 SkBitmap bm; 86 bm.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height()); 87 SkCanvas c(bm); 88 89 Canvas2CanvasClipVisitor visitor(&c); 90 canvas->replayClips(&visitor); 91 92 REPORTER_ASSERT(reporter, c.getTotalClip() == canvas->getTotalClip()); 93 } 94 95 static const int kWidth = 2; 96 static const int kHeight = 2; 97 // Maximum stream length for picture serialization 98 static const size_t kMaxPictureBufferSize = 1024; 99 100 // Format strings that describe the test context. The %s token is where 101 // the name of the test step is inserted. The context is required for 102 // disambiguating the error in the case of failures that are reported in 103 // functions that are called multiple times in different contexts (test 104 // cases and test steps). 105 static const char* const kDefaultAssertMessageFormat = "%s"; 106 static const char* const kCanvasDrawAssertMessageFormat = 107 "Drawing test step %s with SkCanvas"; 108 static const char* const kPictureDrawAssertMessageFormat = 109 "Drawing test step %s with SkPicture"; 110 static const char* const kPictureSecondDrawAssertMessageFormat = 111 "Duplicate draw of test step %s with SkPicture"; 112 static const char* const kPictureReDrawAssertMessageFormat = 113 "Playing back test step %s from an SkPicture to another SkPicture"; 114 static const char* const kDeferredDrawAssertMessageFormat = 115 "Drawing test step %s with SkDeferredCanvas"; 116 static const char* const kProxyDrawAssertMessageFormat = 117 "Drawing test step %s with SkProxyCanvas"; 118 static const char* const kNWayDrawAssertMessageFormat = 119 "Drawing test step %s with SkNWayCanvas"; 120 static const char* const kRoundTripAssertMessageFormat = 121 "test step %s, SkPicture consistency after round trip"; 122 static const char* const kPictureRecoringAssertMessageFormat = 123 "test step %s, SkPicture state consistency after recording"; 124 static const char* const kPicturePlaybackAssertMessageFormat = 125 "test step %s, SkPicture state consistency in playback canvas"; 126 static const char* const kDeferredPreFlushAssertMessageFormat = 127 "test step %s, SkDeferredCanvas state consistency before flush"; 128 static const char* const kDeferredPostFlushPlaybackAssertMessageFormat = 129 "test step %s, SkDeferredCanvas playback canvas state consistency after flush"; 130 static const char* const kDeferredPostSilentFlushPlaybackAssertMessageFormat = 131 "test step %s, SkDeferredCanvas playback canvas state consistency after silent flush"; 132 static const char* const kDeferredPostFlushAssertMessageFormat = 133 "test step %s, SkDeferredCanvas state consistency after flush"; 134 static const char* const kPictureResourceReuseMessageFormat = 135 "test step %s, SkPicture duplicate flattened object test"; 136 static const char* const kProxyStateAssertMessageFormat = 137 "test step %s, SkProxyCanvas state consistency"; 138 static const char* const kProxyIndirectStateAssertMessageFormat = 139 "test step %s, SkProxyCanvas indirect canvas state consistency"; 140 static const char* const kNWayStateAssertMessageFormat = 141 "test step %s, SkNWayCanvas state consistency"; 142 static const char* const kNWayIndirect1StateAssertMessageFormat = 143 "test step %s, SkNWayCanvas indirect canvas 1 state consistency"; 144 static const char* const kNWayIndirect2StateAssertMessageFormat = 145 "test step %s, SkNWayCanvas indirect canvas 2 state consistency"; 146 static const char* const kPdfAssertMessageFormat = 147 "PDF sanity check failed %s"; 148 149 static void createBitmap(SkBitmap* bm, SkBitmap::Config config, SkColor color) { 150 bm->setConfig(config, kWidth, kHeight); 151 bm->allocPixels(); 152 bm->eraseColor(color); 153 } 154 155 class CanvasTestStep; 156 static SkTDArray<CanvasTestStep*>& testStepArray() { 157 static SkTDArray<CanvasTestStep*> theTests; 158 return theTests; 159 } 160 161 class CanvasTestStep { 162 public: 163 CanvasTestStep(bool fEnablePdfTesting = true) { 164 *testStepArray().append() = this; 165 fAssertMessageFormat = kDefaultAssertMessageFormat; 166 this->fEnablePdfTesting = fEnablePdfTesting; 167 } 168 virtual ~CanvasTestStep() { } 169 170 virtual void draw(SkCanvas*, skiatest::Reporter*) = 0; 171 virtual const char* name() const = 0; 172 173 const char* assertMessage() { 174 fAssertMessage.printf(fAssertMessageFormat, name()); 175 return fAssertMessage.c_str(); 176 } 177 178 void setAssertMessageFormat(const char* format) { 179 fAssertMessageFormat = format; 180 } 181 182 bool enablePdfTesting() { return fEnablePdfTesting; } 183 184 private: 185 SkString fAssertMessage; 186 const char* fAssertMessageFormat; 187 bool fEnablePdfTesting; 188 }; 189 190 /////////////////////////////////////////////////////////////////////////////// 191 // Constants used by test steps 192 193 const SkRect kTestRect = 194 SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 195 SkIntToScalar(2), SkIntToScalar(1)); 196 static SkMatrix testMatrix() { 197 SkMatrix matrix; 198 matrix.reset(); 199 matrix.setScale(SkIntToScalar(2), SkIntToScalar(3)); 200 return matrix; 201 } 202 const SkMatrix kTestMatrix = testMatrix(); 203 static SkPath testPath() { 204 SkPath path; 205 path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 206 SkIntToScalar(2), SkIntToScalar(1))); 207 return path; 208 } 209 const SkPath kTestPath = testPath(); 210 static SkRegion testRegion() { 211 SkRegion region; 212 SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1); 213 region.setRect(rect); 214 return region; 215 } 216 const SkIRect kTestIRect = SkIRect::MakeXYWH(0, 0, 2, 1); 217 const SkRegion kTestRegion = testRegion(); 218 const SkColor kTestColor = 0x01020304; 219 const SkPaint kTestPaint; 220 const SkPoint kTestPoints[3] = { 221 {SkIntToScalar(0), SkIntToScalar(0)}, 222 {SkIntToScalar(2), SkIntToScalar(1)}, 223 {SkIntToScalar(0), SkIntToScalar(2)} 224 }; 225 const size_t kTestPointCount = 3; 226 static SkBitmap testBitmap() { 227 SkBitmap bitmap; 228 createBitmap(&bitmap, SkBitmap::kARGB_8888_Config, 0x05060708); 229 return bitmap; 230 } 231 SkBitmap kTestBitmap; // cannot be created during static init 232 SkString kTestText("Hello World"); 233 SkPoint kTestPoints2[] = { 234 { SkIntToScalar(0), SkIntToScalar(1) }, 235 { SkIntToScalar(1), SkIntToScalar(1) }, 236 { SkIntToScalar(2), SkIntToScalar(1) }, 237 { SkIntToScalar(3), SkIntToScalar(1) }, 238 { SkIntToScalar(4), SkIntToScalar(1) }, 239 { SkIntToScalar(5), SkIntToScalar(1) }, 240 { SkIntToScalar(6), SkIntToScalar(1) }, 241 { SkIntToScalar(7), SkIntToScalar(1) }, 242 { SkIntToScalar(8), SkIntToScalar(1) }, 243 { SkIntToScalar(9), SkIntToScalar(1) }, 244 { SkIntToScalar(10), SkIntToScalar(1) }, 245 }; 246 247 248 /////////////////////////////////////////////////////////////////////////////// 249 // Macros for defining test steps 250 251 #define TEST_STEP(NAME, FUNCTION) \ 252 class NAME##_TestStep : public CanvasTestStep{ \ 253 public: \ 254 virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ 255 FUNCTION (canvas, reporter, this); \ 256 } \ 257 virtual const char* name() const {return #NAME ;} \ 258 }; \ 259 static NAME##_TestStep NAME##_TestStepInstance; 260 261 #define TEST_STEP_NO_PDF(NAME, FUNCTION) \ 262 class NAME##_TestStep : public CanvasTestStep{ \ 263 public: \ 264 NAME##_TestStep() : CanvasTestStep(false) {} \ 265 virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ 266 FUNCTION (canvas, reporter, this); \ 267 } \ 268 virtual const char* name() const {return #NAME ;} \ 269 }; \ 270 static NAME##_TestStep NAME##_TestStepInstance; 271 272 #define SIMPLE_TEST_STEP(NAME, CALL) \ 273 static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \ 274 CanvasTestStep*) { \ 275 canvas-> CALL ; \ 276 } \ 277 TEST_STEP(NAME, NAME##TestStep ) 278 279 #define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL) \ 280 static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \ 281 CanvasTestStep* testStep) { \ 282 REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL , \ 283 testStep->assertMessage()); \ 284 } \ 285 TEST_STEP(NAME, NAME##TestStep ) 286 287 288 /////////////////////////////////////////////////////////////////////////////// 289 // Basic test steps for most virtual methods in SkCanvas that draw or affect 290 // the state of the canvas. 291 292 SIMPLE_TEST_STEP_WITH_ASSERT(Translate, 293 translate(SkIntToScalar(1), SkIntToScalar(2))); 294 SIMPLE_TEST_STEP_WITH_ASSERT(Scale, 295 scale(SkIntToScalar(1), SkIntToScalar(2))); 296 SIMPLE_TEST_STEP_WITH_ASSERT(Rotate, rotate(SkIntToScalar(1))); 297 SIMPLE_TEST_STEP_WITH_ASSERT(Skew, 298 skew(SkIntToScalar(1), SkIntToScalar(2))); 299 SIMPLE_TEST_STEP_WITH_ASSERT(Concat, concat(kTestMatrix)); 300 SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix)); 301 SIMPLE_TEST_STEP(ClipRect, clipRect(kTestRect)); 302 SIMPLE_TEST_STEP(ClipPath, clipPath(kTestPath)); 303 SIMPLE_TEST_STEP(ClipRegion, 304 clipRegion(kTestRegion, SkRegion::kReplace_Op)); 305 SIMPLE_TEST_STEP(Clear, clear(kTestColor)); 306 SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint)); 307 SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode, 308 kTestPointCount, kTestPoints, kTestPaint)); 309 SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode, 310 kTestPointCount, kTestPoints, kTestPaint)); 311 SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode, 312 kTestPointCount, kTestPoints, kTestPaint)); 313 SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint)); 314 SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint)); 315 SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0)); 316 SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint)); 317 SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect, 318 NULL)); 319 SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap, 320 &kTestIRect, kTestRect, NULL)); 321 SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL, 322 kTestRect, &kTestPaint)); 323 SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix, 324 NULL)); 325 SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap, 326 kTestMatrix, &kTestPaint)); 327 SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect, 328 kTestRect, NULL)); 329 SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect, 330 kTestRect, &kTestPaint)); 331 SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL)); 332 SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint)); 333 SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(), 334 0, 1, kTestPaint)); 335 SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(), 336 kTestText.size(), kTestPoints2, kTestPaint)); 337 SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(), 338 kTestText.size(), kTestPath, NULL, kTestPaint)); 339 SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(), 340 kTestText.size(), kTestPath, &kTestMatrix, kTestPaint)); 341 SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size())); 342 SIMPLE_TEST_STEP(BeginGroup, beginCommentGroup(kTestText.c_str())); 343 SIMPLE_TEST_STEP(AddComment, addComment(kTestText.c_str(), kTestText.c_str())); 344 SIMPLE_TEST_STEP(EndGroup, endCommentGroup()); 345 346 /////////////////////////////////////////////////////////////////////////////// 347 // Complex test steps 348 349 // Save/restore calls cannot be in isolated simple test steps because the test 350 // cases that use SkPicture require that save and restore calls be balanced. 351 static void SaveMatrixStep(SkCanvas* canvas, 352 skiatest::Reporter* reporter, 353 CanvasTestStep* testStep) { 354 int saveCount = canvas->getSaveCount(); 355 canvas->save(SkCanvas::kMatrix_SaveFlag); 356 canvas->clipRegion(kTestRegion); 357 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 358 canvas->restore(); 359 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 360 testStep->assertMessage()); 361 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 362 testStep->assertMessage()); 363 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() == kTestRegion, 364 testStep->assertMessage()); 365 } 366 TEST_STEP(SaveMatrix, SaveMatrixStep); 367 368 static void SaveClipStep(SkCanvas* canvas, 369 skiatest::Reporter* reporter, 370 CanvasTestStep* testStep) { 371 int saveCount = canvas->getSaveCount(); 372 canvas->save(SkCanvas::kClip_SaveFlag); 373 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 374 canvas->clipRegion(kTestRegion); 375 canvas->restore(); 376 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 377 testStep->assertMessage()); 378 REPORTER_ASSERT_MESSAGE(reporter, !canvas->getTotalMatrix().isIdentity(), 379 testStep->assertMessage()); 380 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 381 testStep->assertMessage()); 382 } 383 TEST_STEP(SaveClip, SaveClipStep); 384 385 static void SaveMatrixClipStep(SkCanvas* canvas, 386 skiatest::Reporter* reporter, 387 CanvasTestStep* testStep) { 388 int saveCount = canvas->getSaveCount(); 389 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 390 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 391 canvas->clipRegion(kTestRegion); 392 canvas->restore(); 393 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 394 testStep->assertMessage()); 395 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 396 testStep->assertMessage()); 397 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 398 testStep->assertMessage()); 399 } 400 TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 401 402 static void SaveLayerStep(SkCanvas* canvas, 403 skiatest::Reporter* reporter, 404 CanvasTestStep* testStep) { 405 int saveCount = canvas->getSaveCount(); 406 canvas->saveLayer(NULL, NULL); 407 canvas->restore(); 408 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 409 testStep->assertMessage()); 410 } 411 TEST_STEP(SaveLayer, SaveLayerStep); 412 413 static void BoundedSaveLayerStep(SkCanvas* canvas, 414 skiatest::Reporter* reporter, 415 CanvasTestStep* testStep) { 416 int saveCount = canvas->getSaveCount(); 417 canvas->saveLayer(&kTestRect, NULL); 418 canvas->restore(); 419 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 420 testStep->assertMessage()); 421 } 422 TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 423 424 static void PaintSaveLayerStep(SkCanvas* canvas, 425 skiatest::Reporter* reporter, 426 CanvasTestStep* testStep) { 427 int saveCount = canvas->getSaveCount(); 428 canvas->saveLayer(NULL, &kTestPaint); 429 canvas->restore(); 430 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 431 testStep->assertMessage()); 432 } 433 TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 434 435 static void TwoClipOpsStep(SkCanvas* canvas, 436 skiatest::Reporter*, 437 CanvasTestStep*) { 438 // This test exercises a functionality in SkPicture that leads to the 439 // recording of restore offset placeholders. This test will trigger an 440 // assertion at playback time if the placeholders are not properly 441 // filled when the recording ends. 442 canvas->clipRect(kTestRect); 443 canvas->clipRegion(kTestRegion); 444 } 445 TEST_STEP(TwoClipOps, TwoClipOpsStep); 446 447 // exercise fix for http://code.google.com/p/skia/issues/detail?id=560 448 // ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 449 static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, 450 skiatest::Reporter*, 451 CanvasTestStep*) { 452 SkPaint paint; 453 paint.setStrokeWidth(SkIntToScalar(1)); 454 paint.setStyle(SkPaint::kStroke_Style); 455 456 SkPath path; 457 SkPoint pt1 = { 0, 0 }; 458 SkPoint pt2 = { 0, SK_ScalarNearlyZero }; 459 SkPoint pt3 = { SkIntToScalar(1), 0 }; 460 SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; 461 path.moveTo(pt1); 462 path.lineTo(pt2); 463 path.lineTo(pt3); 464 path.lineTo(pt4); 465 466 canvas->drawPath(path, paint); 467 } 468 TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 469 470 static void DrawVerticesShaderTestStep(SkCanvas* canvas, 471 skiatest::Reporter*, 472 CanvasTestStep*) { 473 SkPoint pts[4]; 474 pts[0].set(0, 0); 475 pts[1].set(SkIntToScalar(kWidth), 0); 476 pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 477 pts[3].set(0, SkIntToScalar(kHeight)); 478 SkPaint paint; 479 SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, 480 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 481 paint.setShader(shader)->unref(); 482 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 483 NULL, NULL, NULL, 0, paint); 484 } 485 // NYI: issue 240. 486 TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); 487 488 static void DrawPictureTestStep(SkCanvas* canvas, 489 skiatest::Reporter*, 490 CanvasTestStep*) { 491 SkPicture* testPicture = SkNEW_ARGS(SkPicture, ()); 492 SkAutoUnref aup(testPicture); 493 SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight); 494 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 495 testCanvas->clipRect(kTestRect); 496 testCanvas->drawRect(kTestRect, kTestPaint); 497 canvas->drawPicture(*testPicture); 498 } 499 TEST_STEP(DrawPicture, DrawPictureTestStep); 500 501 static void SaveRestoreTestStep(SkCanvas* canvas, 502 skiatest::Reporter* reporter, 503 CanvasTestStep* testStep) { 504 int baseSaveCount = canvas->getSaveCount(); 505 int n = canvas->save(); 506 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 507 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 508 testStep->assertMessage()); 509 canvas->save(); 510 canvas->save(); 511 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 512 testStep->assertMessage()); 513 canvas->restoreToCount(baseSaveCount + 1); 514 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 515 testStep->assertMessage()); 516 517 // should this pin to 1, or be a no-op, or crash? 518 canvas->restoreToCount(0); 519 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 520 testStep->assertMessage()); 521 } 522 TEST_STEP(SaveRestore, SaveRestoreTestStep); 523 524 static void DrawLayerTestStep(SkCanvas* canvas, 525 skiatest::Reporter* reporter, 526 CanvasTestStep* testStep) { 527 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 528 testStep->assertMessage()); 529 canvas->save(); 530 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 531 testStep->assertMessage()); 532 canvas->restore(); 533 534 const SkRect* bounds = NULL; // null means include entire bounds 535 const SkPaint* paint = NULL; 536 537 canvas->saveLayer(bounds, paint); 538 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 539 testStep->assertMessage()); 540 canvas->restore(); 541 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 542 testStep->assertMessage()); 543 544 canvas->saveLayer(bounds, paint); 545 canvas->saveLayer(bounds, paint); 546 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 547 testStep->assertMessage()); 548 canvas->restore(); 549 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 550 testStep->assertMessage()); 551 canvas->restore(); 552 // now layer count should be 0 553 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 554 testStep->assertMessage()); 555 } 556 TEST_STEP(DrawLayer, DrawLayerTestStep); 557 558 static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, 559 skiatest::Reporter*, 560 CanvasTestStep*) { 561 // This test step challenges the TestDeferredCanvasStateConsistency 562 // test cases because the opaque paint can trigger an optimization 563 // that discards previously recorded commands. The challenge is to maintain 564 // correct clip and matrix stack state. 565 canvas->resetMatrix(); 566 canvas->rotate(SkIntToScalar(30)); 567 canvas->save(); 568 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 569 canvas->save(); 570 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 571 SkPaint paint; 572 paint.setColor(0xFFFFFFFF); 573 canvas->drawPaint(paint); 574 canvas->restore(); 575 canvas->restore(); 576 } 577 TEST_STEP(NestedSaveRestoreWithSolidPaint, \ 578 NestedSaveRestoreWithSolidPaintTestStep); 579 580 static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, 581 skiatest::Reporter*, 582 CanvasTestStep*) { 583 // This test step challenges the TestDeferredCanvasStateConsistency 584 // test case because the canvas flush on a deferred canvas will 585 // reset the recording session. The challenge is to maintain correct 586 // clip and matrix stack state on the playback canvas. 587 canvas->resetMatrix(); 588 canvas->rotate(SkIntToScalar(30)); 589 canvas->save(); 590 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 591 canvas->save(); 592 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 593 canvas->drawRect(kTestRect,kTestPaint); 594 canvas->flush(); 595 canvas->restore(); 596 canvas->restore(); 597 } 598 TEST_STEP(NestedSaveRestoreWithFlush, \ 599 NestedSaveRestoreWithFlushTestStep); 600 601 static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, 602 const SkCanvas* canvas1, 603 const SkCanvas* canvas2, 604 CanvasTestStep* testStep) { 605 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 606 canvas2->getDeviceSize(), testStep->assertMessage()); 607 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 608 canvas2->getSaveCount(), testStep->assertMessage()); 609 REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == 610 canvas2->isDrawingToLayer(), testStep->assertMessage()); 611 612 SkRect bounds1, bounds2; 613 REPORTER_ASSERT_MESSAGE(reporter, 614 canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), 615 testStep->assertMessage()); 616 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 617 testStep->assertMessage()); 618 619 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 620 canvas2->getDrawFilter(), testStep->assertMessage()); 621 SkIRect deviceBounds1, deviceBounds2; 622 REPORTER_ASSERT_MESSAGE(reporter, 623 canvas1->getClipDeviceBounds(&deviceBounds1) == 624 canvas2->getClipDeviceBounds(&deviceBounds2), 625 testStep->assertMessage()); 626 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, 627 testStep->assertMessage()); 628 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 629 canvas2->getBounder(), testStep->assertMessage()); 630 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 631 canvas2->getTotalMatrix(), testStep->assertMessage()); 632 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getClipType() == 633 canvas2->getClipType(), testStep->assertMessage()); 634 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() == 635 canvas2->getTotalClip(), testStep->assertMessage()); 636 637 // The following test code is commented out because the test fails when 638 // the canvas is an SkPictureRecord or SkDeferredCanvas 639 // Issue: http://code.google.com/p/skia/issues/detail?id=498 640 // Also, creating a LayerIter on an SkProxyCanvas crashes 641 // Issue: http://code.google.com/p/skia/issues/detail?id=499 642 /* 643 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 644 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 645 while (!layerIter1.done() && !layerIter2.done()) { 646 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 647 layerIter2.matrix(), testStep->assertMessage()); 648 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 649 layerIter2.clip(), testStep->assertMessage()); 650 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 651 layerIter2.paint(), testStep->assertMessage()); 652 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 653 layerIter2.x(), testStep->assertMessage()); 654 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 655 layerIter2.y(), testStep->assertMessage()); 656 layerIter1.next(); 657 layerIter2.next(); 658 } 659 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 660 testStep->assertMessage()); 661 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 662 testStep->assertMessage()); 663 */ 664 } 665 666 // The following class groups static functions that need to access 667 // the privates members of SkPictureRecord 668 class SkPictureTester { 669 private: 670 static int EQ(const SkFlatData* a, const SkFlatData* b) { 671 return *a == *b; 672 } 673 674 static void AssertFlattenedObjectsEqual( 675 SkPictureRecord* referenceRecord, 676 SkPictureRecord* testRecord, 677 skiatest::Reporter* reporter, 678 CanvasTestStep* testStep) { 679 680 REPORTER_ASSERT_MESSAGE(reporter, 681 referenceRecord->fBitmapHeap->count() == 682 testRecord->fBitmapHeap->count(), testStep->assertMessage()); 683 REPORTER_ASSERT_MESSAGE(reporter, 684 referenceRecord->fMatrices.count() == 685 testRecord->fMatrices.count(), testStep->assertMessage()); 686 for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) { 687 REPORTER_ASSERT_MESSAGE(reporter, 688 EQ(referenceRecord->fMatrices[i], testRecord->fMatrices[i]), 689 testStep->assertMessage()); 690 } 691 REPORTER_ASSERT_MESSAGE(reporter, 692 referenceRecord->fPaints.count() == 693 testRecord->fPaints.count(), testStep->assertMessage()); 694 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 695 REPORTER_ASSERT_MESSAGE(reporter, 696 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 697 testStep->assertMessage()); 698 } 699 REPORTER_ASSERT_MESSAGE(reporter, 700 referenceRecord->fRegions.count() == 701 testRecord->fRegions.count(), testStep->assertMessage()); 702 for (int i = 0; i < referenceRecord->fRegions.count(); ++i) { 703 REPORTER_ASSERT_MESSAGE(reporter, 704 EQ(referenceRecord->fRegions[i], testRecord->fRegions[i]), 705 testStep->assertMessage()); 706 } 707 REPORTER_ASSERT_MESSAGE(reporter, 708 !referenceRecord->fPathHeap == 709 !testRecord->fPathHeap, 710 testStep->assertMessage()); 711 // The following tests are commented out because they currently 712 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 713 /* 714 if (referenceRecord->fPathHeap) { 715 REPORTER_ASSERT_MESSAGE(reporter, 716 referenceRecord->fPathHeap->count() == 717 testRecord->fPathHeap->count(), 718 testStep->assertMessage()); 719 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 720 REPORTER_ASSERT_MESSAGE(reporter, 721 (*referenceRecord->fPathHeap)[i] == 722 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 723 } 724 } 725 */ 726 727 } 728 729 public: 730 731 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 732 CanvasTestStep* testStep, 733 uint32_t recordFlags) { 734 // Verify that when a test step is executed twice, no extra resources 735 // are flattened during the second execution 736 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 737 SkPicture referencePicture; 738 SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth, 739 kHeight, recordFlags); 740 testStep->draw(referenceCanvas, reporter); 741 SkPicture testPicture; 742 SkCanvas* testCanvas = testPicture.beginRecording(kWidth, 743 kHeight, recordFlags); 744 testStep->draw(testCanvas, reporter); 745 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 746 testStep->draw(testCanvas, reporter); 747 748 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>( 749 referenceCanvas); 750 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>( 751 testCanvas); 752 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 753 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 754 reporter, testStep); 755 } 756 }; 757 758 static void TestPdfDevice(skiatest::Reporter* reporter, 759 CanvasTestStep* testStep) { 760 SkISize pageSize = SkISize::Make(kWidth, kHeight); 761 SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); 762 SkCanvas canvas(&device); 763 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 764 testStep->draw(&canvas, reporter); 765 SkPDFDocument doc; 766 doc.appendPage(&device); 767 SkDynamicMemoryWStream stream; 768 doc.emitPDF(&stream); 769 } 770 771 // The following class groups static functions that need to access 772 // the privates members of SkDeferredCanvas 773 class SkDeferredCanvasTester { 774 public: 775 static void TestDeferredCanvasStateConsistency( 776 skiatest::Reporter* reporter, 777 CanvasTestStep* testStep, 778 const SkCanvas& referenceCanvas, bool silent) { 779 780 SkBitmap deferredStore; 781 createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 782 SkDevice deferredDevice(deferredStore); 783 SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(&deferredDevice)); 784 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 785 testStep->draw(deferredCanvas, reporter); 786 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 787 AssertCanvasStatesEqual(reporter, deferredCanvas, &referenceCanvas, 788 testStep); 789 790 if (silent) { 791 deferredCanvas->silentFlush(); 792 } else { 793 deferredCanvas->flush(); 794 } 795 796 testStep->setAssertMessageFormat( 797 silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : 798 kDeferredPostFlushPlaybackAssertMessageFormat); 799 AssertCanvasStatesEqual(reporter, 800 deferredCanvas->immediateCanvas(), 801 &referenceCanvas, testStep); 802 803 // Verified that deferred canvas state is not affected by flushing 804 // pending draw operations 805 806 // The following test code is commented out because it currently fails. 807 // Issue: http://code.google.com/p/skia/issues/detail?id=496 808 /* 809 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 810 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 811 testStep); 812 */ 813 } 814 }; 815 816 // unused 817 static void TestProxyCanvasStateConsistency( 818 skiatest::Reporter* reporter, 819 CanvasTestStep* testStep, 820 const SkCanvas& referenceCanvas) { 821 822 SkBitmap indirectStore; 823 createBitmap(&indirectStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 824 SkDevice indirectDevice(indirectStore); 825 SkCanvas indirectCanvas(&indirectDevice); 826 SkProxyCanvas proxyCanvas(&indirectCanvas); 827 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 828 testStep->draw(&proxyCanvas, reporter); 829 // Verify that the SkProxyCanvas reports consitent state 830 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 831 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 832 testStep); 833 // Verify that the indirect canvas reports consitent state 834 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 835 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 836 testStep); 837 } 838 839 // unused 840 static void TestNWayCanvasStateConsistency( 841 skiatest::Reporter* reporter, 842 CanvasTestStep* testStep, 843 const SkCanvas& referenceCanvas) { 844 845 SkBitmap indirectStore1; 846 createBitmap(&indirectStore1, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 847 SkDevice indirectDevice1(indirectStore1); 848 SkCanvas indirectCanvas1(&indirectDevice1); 849 850 SkBitmap indirectStore2; 851 createBitmap(&indirectStore2, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 852 SkDevice indirectDevice2(indirectStore2); 853 SkCanvas indirectCanvas2(&indirectDevice2); 854 855 SkISize canvasSize = referenceCanvas.getDeviceSize(); 856 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 857 nWayCanvas.addCanvas(&indirectCanvas1); 858 nWayCanvas.addCanvas(&indirectCanvas2); 859 860 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 861 testStep->draw(&nWayCanvas, reporter); 862 // Verify that the SkProxyCanvas reports consitent state 863 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 864 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 865 testStep); 866 // Verify that the indirect canvases report consitent state 867 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 868 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 869 testStep); 870 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 871 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 872 testStep); 873 } 874 875 /* 876 * This sub-test verifies that the test step passes when executed 877 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 878 * that the all canvas derivatives report the same state as an SkCanvas 879 * after having executed the test step. 880 */ 881 static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 882 CanvasTestStep* testStep) { 883 SkBitmap referenceStore; 884 createBitmap(&referenceStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 885 SkDevice referenceDevice(referenceStore); 886 SkCanvas referenceCanvas(&referenceDevice); 887 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 888 testStep->draw(&referenceCanvas, reporter); 889 890 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); 891 892 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); 893 894 // The following test code is disabled because SkProxyCanvas is 895 // missing a lot of virtual overrides on get* methods, which are used 896 // to verify canvas state. 897 // Issue: http://code.google.com/p/skia/issues/detail?id=500 898 899 if (false) { // avoid bit rot, suppress warning 900 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 901 } 902 903 // The following test code is disabled because SkNWayCanvas does not 904 // report correct clipping and device bounds information 905 // Issue: http://code.google.com/p/skia/issues/detail?id=501 906 907 if (false) { // avoid bit rot, suppress warning 908 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 909 } 910 911 if (false) { // avoid bit rot, suppress warning 912 test_clipVisitor(reporter, &referenceCanvas); 913 } 914 } 915 916 static void TestCanvas(skiatest::Reporter* reporter) { 917 // Init global here because bitmap pixels cannot be alocated during 918 // static initialization 919 kTestBitmap = testBitmap(); 920 921 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 922 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 923 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 924 testStepArray()[testStep], 0); 925 if (testStepArray()[testStep]->enablePdfTesting()) { 926 TestPdfDevice(reporter, testStepArray()[testStep]); 927 } 928 } 929 930 // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) 931 kTestBitmap.reset(); 932 } 933 934 #include "TestClassDef.h" 935 DEFINE_TESTCLASS("Canvas", TestCanvasClass, TestCanvas) 936