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 343 /////////////////////////////////////////////////////////////////////////////// 344 // Complex test steps 345 346 // Save/restore calls cannot be in isolated simple test steps because the test 347 // cases that use SkPicture require that save and restore calls be balanced. 348 static void SaveMatrixStep(SkCanvas* canvas, 349 skiatest::Reporter* reporter, 350 CanvasTestStep* testStep) { 351 int saveCount = canvas->getSaveCount(); 352 canvas->save(SkCanvas::kMatrix_SaveFlag); 353 canvas->clipRegion(kTestRegion); 354 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 355 canvas->restore(); 356 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 357 testStep->assertMessage()); 358 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 359 testStep->assertMessage()); 360 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() == kTestRegion, 361 testStep->assertMessage()); 362 } 363 TEST_STEP(SaveMatrix, SaveMatrixStep); 364 365 static void SaveClipStep(SkCanvas* canvas, 366 skiatest::Reporter* reporter, 367 CanvasTestStep* testStep) { 368 int saveCount = canvas->getSaveCount(); 369 canvas->save(SkCanvas::kClip_SaveFlag); 370 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 371 canvas->clipRegion(kTestRegion); 372 canvas->restore(); 373 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 374 testStep->assertMessage()); 375 REPORTER_ASSERT_MESSAGE(reporter, !canvas->getTotalMatrix().isIdentity(), 376 testStep->assertMessage()); 377 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 378 testStep->assertMessage()); 379 } 380 TEST_STEP(SaveClip, SaveClipStep); 381 382 static void SaveMatrixClipStep(SkCanvas* canvas, 383 skiatest::Reporter* reporter, 384 CanvasTestStep* testStep) { 385 int saveCount = canvas->getSaveCount(); 386 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 387 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 388 canvas->clipRegion(kTestRegion); 389 canvas->restore(); 390 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 391 testStep->assertMessage()); 392 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 393 testStep->assertMessage()); 394 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 395 testStep->assertMessage()); 396 } 397 TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 398 399 static void SaveLayerStep(SkCanvas* canvas, 400 skiatest::Reporter* reporter, 401 CanvasTestStep* testStep) { 402 int saveCount = canvas->getSaveCount(); 403 canvas->saveLayer(NULL, NULL); 404 canvas->restore(); 405 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 406 testStep->assertMessage()); 407 } 408 TEST_STEP(SaveLayer, SaveLayerStep); 409 410 static void BoundedSaveLayerStep(SkCanvas* canvas, 411 skiatest::Reporter* reporter, 412 CanvasTestStep* testStep) { 413 int saveCount = canvas->getSaveCount(); 414 canvas->saveLayer(&kTestRect, NULL); 415 canvas->restore(); 416 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 417 testStep->assertMessage()); 418 } 419 TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 420 421 static void PaintSaveLayerStep(SkCanvas* canvas, 422 skiatest::Reporter* reporter, 423 CanvasTestStep* testStep) { 424 int saveCount = canvas->getSaveCount(); 425 canvas->saveLayer(NULL, &kTestPaint); 426 canvas->restore(); 427 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 428 testStep->assertMessage()); 429 } 430 TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 431 432 static void TwoClipOpsStep(SkCanvas* canvas, 433 skiatest::Reporter* reporter, 434 CanvasTestStep* testStep) { 435 // This test exercises a functionality in SkPicture that leads to the 436 // recording of restore offset placeholders. This test will trigger an 437 // assertion at playback time if the placeholders are not properly 438 // filled when the recording ends. 439 canvas->clipRect(kTestRect); 440 canvas->clipRegion(kTestRegion); 441 } 442 TEST_STEP(TwoClipOps, TwoClipOpsStep); 443 444 // exercise fix for http://code.google.com/p/skia/issues/detail?id=560 445 // ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 446 static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, 447 skiatest::Reporter* reporter, 448 CanvasTestStep* testStep) { 449 SkPaint paint; 450 paint.setStrokeWidth(SkIntToScalar(1)); 451 paint.setStyle(SkPaint::kStroke_Style); 452 453 SkPath path; 454 SkPoint pt1 = { 0, 0 }; 455 SkPoint pt2 = { 0, SK_ScalarNearlyZero }; 456 SkPoint pt3 = { SkIntToScalar(1), 0 }; 457 SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; 458 path.moveTo(pt1); 459 path.lineTo(pt2); 460 path.lineTo(pt3); 461 path.lineTo(pt4); 462 463 canvas->drawPath(path, paint); 464 } 465 TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 466 467 static void DrawVerticesShaderTestStep(SkCanvas* canvas, 468 skiatest::Reporter* reporter, 469 CanvasTestStep* testStep) { 470 SkPoint pts[4]; 471 pts[0].set(0, 0); 472 pts[1].set(SkIntToScalar(kWidth), 0); 473 pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 474 pts[3].set(0, SkIntToScalar(kHeight)); 475 SkPaint paint; 476 SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, 477 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 478 paint.setShader(shader)->unref(); 479 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 480 NULL, NULL, NULL, 0, paint); 481 } 482 // NYI: issue 240. 483 TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); 484 485 static void DrawPictureTestStep(SkCanvas* canvas, 486 skiatest::Reporter* reporter, 487 CanvasTestStep* testStep) { 488 SkPicture* testPicture = SkNEW_ARGS(SkPicture, ()); 489 SkAutoUnref aup(testPicture); 490 SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight); 491 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 492 testCanvas->clipRect(kTestRect); 493 testCanvas->drawRect(kTestRect, kTestPaint); 494 canvas->drawPicture(*testPicture); 495 } 496 TEST_STEP(DrawPicture, DrawPictureTestStep); 497 498 static void SaveRestoreTestStep(SkCanvas* canvas, 499 skiatest::Reporter* reporter, 500 CanvasTestStep* testStep) { 501 int baseSaveCount = canvas->getSaveCount(); 502 int n = canvas->save(); 503 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 504 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 505 testStep->assertMessage()); 506 canvas->save(); 507 canvas->save(); 508 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 509 testStep->assertMessage()); 510 canvas->restoreToCount(baseSaveCount + 1); 511 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 512 testStep->assertMessage()); 513 514 // should this pin to 1, or be a no-op, or crash? 515 canvas->restoreToCount(0); 516 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 517 testStep->assertMessage()); 518 } 519 TEST_STEP(SaveRestore, SaveRestoreTestStep); 520 521 static void DrawLayerTestStep(SkCanvas* canvas, 522 skiatest::Reporter* reporter, 523 CanvasTestStep* testStep) { 524 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 525 testStep->assertMessage()); 526 canvas->save(); 527 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 528 testStep->assertMessage()); 529 canvas->restore(); 530 531 const SkRect* bounds = NULL; // null means include entire bounds 532 const SkPaint* paint = NULL; 533 534 canvas->saveLayer(bounds, paint); 535 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 536 testStep->assertMessage()); 537 canvas->restore(); 538 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 539 testStep->assertMessage()); 540 541 canvas->saveLayer(bounds, paint); 542 canvas->saveLayer(bounds, paint); 543 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 544 testStep->assertMessage()); 545 canvas->restore(); 546 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 547 testStep->assertMessage()); 548 canvas->restore(); 549 // now layer count should be 0 550 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 551 testStep->assertMessage()); 552 } 553 TEST_STEP(DrawLayer, DrawLayerTestStep); 554 555 static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, 556 skiatest::Reporter* reporter, 557 CanvasTestStep* testStep) { 558 // This test step challenges the TestDeferredCanvasStateConsistency 559 // test cases because the opaque paint can trigger an optimization 560 // that discards previously recorded commands. The challenge is to maintain 561 // correct clip and matrix stack state. 562 canvas->resetMatrix(); 563 canvas->rotate(SkIntToScalar(30)); 564 canvas->save(); 565 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 566 canvas->save(); 567 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 568 SkPaint paint; 569 paint.setColor(0xFFFFFFFF); 570 canvas->drawPaint(paint); 571 canvas->restore(); 572 canvas->restore(); 573 } 574 TEST_STEP(NestedSaveRestoreWithSolidPaint, \ 575 NestedSaveRestoreWithSolidPaintTestStep); 576 577 static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, 578 skiatest::Reporter* reporter, 579 CanvasTestStep* testStep) { 580 // This test step challenges the TestDeferredCanvasStateConsistency 581 // test case because the canvas flush on a deferred canvas will 582 // reset the recording session. The challenge is to maintain correct 583 // clip and matrix stack state on the playback canvas. 584 canvas->resetMatrix(); 585 canvas->rotate(SkIntToScalar(30)); 586 canvas->save(); 587 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 588 canvas->save(); 589 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 590 canvas->drawRect(kTestRect,kTestPaint); 591 canvas->flush(); 592 canvas->restore(); 593 canvas->restore(); 594 } 595 TEST_STEP(NestedSaveRestoreWithFlush, \ 596 NestedSaveRestoreWithFlushTestStep); 597 598 static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, 599 const SkCanvas* canvas1, 600 const SkCanvas* canvas2, 601 CanvasTestStep* testStep) { 602 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 603 canvas2->getDeviceSize(), testStep->assertMessage()); 604 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 605 canvas2->getSaveCount(), testStep->assertMessage()); 606 REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == 607 canvas2->isDrawingToLayer(), testStep->assertMessage()); 608 609 SkRect bounds1, bounds2; 610 REPORTER_ASSERT_MESSAGE(reporter, 611 canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), 612 testStep->assertMessage()); 613 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 614 testStep->assertMessage()); 615 616 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 617 canvas2->getDrawFilter(), testStep->assertMessage()); 618 SkIRect deviceBounds1, deviceBounds2; 619 REPORTER_ASSERT_MESSAGE(reporter, 620 canvas1->getClipDeviceBounds(&deviceBounds1) == 621 canvas2->getClipDeviceBounds(&deviceBounds2), 622 testStep->assertMessage()); 623 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, 624 testStep->assertMessage()); 625 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 626 canvas2->getBounder(), testStep->assertMessage()); 627 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 628 canvas2->getTotalMatrix(), testStep->assertMessage()); 629 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getClipType() == 630 canvas2->getClipType(), testStep->assertMessage()); 631 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() == 632 canvas2->getTotalClip(), testStep->assertMessage()); 633 634 // The following test code is commented out because the test fails when 635 // the canvas is an SkPictureRecord or SkDeferredCanvas 636 // Issue: http://code.google.com/p/skia/issues/detail?id=498 637 // Also, creating a LayerIter on an SkProxyCanvas crashes 638 // Issue: http://code.google.com/p/skia/issues/detail?id=499 639 /* 640 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 641 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 642 while (!layerIter1.done() && !layerIter2.done()) { 643 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 644 layerIter2.matrix(), testStep->assertMessage()); 645 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 646 layerIter2.clip(), testStep->assertMessage()); 647 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 648 layerIter2.paint(), testStep->assertMessage()); 649 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 650 layerIter2.x(), testStep->assertMessage()); 651 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 652 layerIter2.y(), testStep->assertMessage()); 653 layerIter1.next(); 654 layerIter2.next(); 655 } 656 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 657 testStep->assertMessage()); 658 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 659 testStep->assertMessage()); 660 */ 661 } 662 663 // The following class groups static functions that need to access 664 // the privates members of SkPictureRecord 665 class SkPictureTester { 666 private: 667 static int EQ(const SkFlatData* a, const SkFlatData* b) { 668 return *a == *b; 669 } 670 671 static void AssertFlattenedObjectsEqual( 672 SkPictureRecord* referenceRecord, 673 SkPictureRecord* testRecord, 674 skiatest::Reporter* reporter, 675 CanvasTestStep* testStep) { 676 677 REPORTER_ASSERT_MESSAGE(reporter, 678 referenceRecord->fBitmapHeap->count() == 679 testRecord->fBitmapHeap->count(), testStep->assertMessage()); 680 REPORTER_ASSERT_MESSAGE(reporter, 681 referenceRecord->fMatrices.count() == 682 testRecord->fMatrices.count(), testStep->assertMessage()); 683 for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) { 684 REPORTER_ASSERT_MESSAGE(reporter, 685 EQ(referenceRecord->fMatrices[i], testRecord->fMatrices[i]), 686 testStep->assertMessage()); 687 } 688 REPORTER_ASSERT_MESSAGE(reporter, 689 referenceRecord->fPaints.count() == 690 testRecord->fPaints.count(), testStep->assertMessage()); 691 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 692 REPORTER_ASSERT_MESSAGE(reporter, 693 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 694 testStep->assertMessage()); 695 } 696 REPORTER_ASSERT_MESSAGE(reporter, 697 referenceRecord->fRegions.count() == 698 testRecord->fRegions.count(), testStep->assertMessage()); 699 for (int i = 0; i < referenceRecord->fRegions.count(); ++i) { 700 REPORTER_ASSERT_MESSAGE(reporter, 701 EQ(referenceRecord->fRegions[i], testRecord->fRegions[i]), 702 testStep->assertMessage()); 703 } 704 REPORTER_ASSERT_MESSAGE(reporter, 705 !referenceRecord->fPathHeap == 706 !testRecord->fPathHeap, 707 testStep->assertMessage()); 708 // The following tests are commented out because they currently 709 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 710 /* 711 if (referenceRecord->fPathHeap) { 712 REPORTER_ASSERT_MESSAGE(reporter, 713 referenceRecord->fPathHeap->count() == 714 testRecord->fPathHeap->count(), 715 testStep->assertMessage()); 716 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 717 REPORTER_ASSERT_MESSAGE(reporter, 718 (*referenceRecord->fPathHeap)[i] == 719 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 720 } 721 } 722 */ 723 724 } 725 726 public: 727 728 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 729 CanvasTestStep* testStep, 730 uint32_t recordFlags) { 731 // Verify that when a test step is executed twice, no extra resources 732 // are flattened during the second execution 733 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 734 SkPicture referencePicture; 735 SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth, 736 kHeight, recordFlags); 737 testStep->draw(referenceCanvas, reporter); 738 SkPicture testPicture; 739 SkCanvas* testCanvas = testPicture.beginRecording(kWidth, 740 kHeight, recordFlags); 741 testStep->draw(testCanvas, reporter); 742 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 743 testStep->draw(testCanvas, reporter); 744 745 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>( 746 referenceCanvas); 747 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>( 748 testCanvas); 749 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 750 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 751 reporter, testStep); 752 } 753 }; 754 755 static void TestPdfDevice(skiatest::Reporter* reporter, 756 CanvasTestStep* testStep) { 757 SkISize pageSize = SkISize::Make(kWidth, kHeight); 758 SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); 759 SkCanvas canvas(&device); 760 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 761 testStep->draw(&canvas, reporter); 762 SkPDFDocument doc; 763 doc.appendPage(&device); 764 SkDynamicMemoryWStream stream; 765 doc.emitPDF(&stream); 766 } 767 768 // The following class groups static functions that need to access 769 // the privates members of SkDeferredCanvas 770 class SkDeferredCanvasTester { 771 public: 772 static void TestDeferredCanvasStateConsistency( 773 skiatest::Reporter* reporter, 774 CanvasTestStep* testStep, 775 const SkCanvas& referenceCanvas, bool silent) { 776 777 SkBitmap deferredStore; 778 createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 779 SkDevice deferredDevice(deferredStore); 780 SkDeferredCanvas deferredCanvas(&deferredDevice); 781 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 782 testStep->draw(&deferredCanvas, reporter); 783 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 784 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 785 testStep); 786 787 if (silent) { 788 deferredCanvas.silentFlush(); 789 } else { 790 deferredCanvas.flush(); 791 } 792 793 testStep->setAssertMessageFormat( 794 silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : 795 kDeferredPostFlushPlaybackAssertMessageFormat); 796 AssertCanvasStatesEqual(reporter, 797 deferredCanvas.immediateCanvas(), 798 &referenceCanvas, testStep); 799 800 // Verified that deferred canvas state is not affected by flushing 801 // pending draw operations 802 803 // The following test code is commented out because it currently fails. 804 // Issue: http://code.google.com/p/skia/issues/detail?id=496 805 /* 806 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 807 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 808 testStep); 809 */ 810 } 811 }; 812 813 // unused 814 static void TestProxyCanvasStateConsistency( 815 skiatest::Reporter* reporter, 816 CanvasTestStep* testStep, 817 const SkCanvas& referenceCanvas) { 818 819 SkBitmap indirectStore; 820 createBitmap(&indirectStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 821 SkDevice indirectDevice(indirectStore); 822 SkCanvas indirectCanvas(&indirectDevice); 823 SkProxyCanvas proxyCanvas(&indirectCanvas); 824 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 825 testStep->draw(&proxyCanvas, reporter); 826 // Verify that the SkProxyCanvas reports consitent state 827 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 828 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 829 testStep); 830 // Verify that the indirect canvas reports consitent state 831 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 832 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 833 testStep); 834 } 835 836 // unused 837 static void TestNWayCanvasStateConsistency( 838 skiatest::Reporter* reporter, 839 CanvasTestStep* testStep, 840 const SkCanvas& referenceCanvas) { 841 842 SkBitmap indirectStore1; 843 createBitmap(&indirectStore1, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 844 SkDevice indirectDevice1(indirectStore1); 845 SkCanvas indirectCanvas1(&indirectDevice1); 846 847 SkBitmap indirectStore2; 848 createBitmap(&indirectStore2, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 849 SkDevice indirectDevice2(indirectStore2); 850 SkCanvas indirectCanvas2(&indirectDevice2); 851 852 SkISize canvasSize = referenceCanvas.getDeviceSize(); 853 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 854 nWayCanvas.addCanvas(&indirectCanvas1); 855 nWayCanvas.addCanvas(&indirectCanvas2); 856 857 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 858 testStep->draw(&nWayCanvas, reporter); 859 // Verify that the SkProxyCanvas reports consitent state 860 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 861 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 862 testStep); 863 // Verify that the indirect canvases report consitent state 864 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 865 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 866 testStep); 867 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 868 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 869 testStep); 870 } 871 872 /* 873 * This sub-test verifies that the test step passes when executed 874 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 875 * that the all canvas derivatives report the same state as an SkCanvas 876 * after having executed the test step. 877 */ 878 static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 879 CanvasTestStep* testStep) { 880 SkBitmap referenceStore; 881 createBitmap(&referenceStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 882 SkDevice referenceDevice(referenceStore); 883 SkCanvas referenceCanvas(&referenceDevice); 884 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 885 testStep->draw(&referenceCanvas, reporter); 886 887 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); 888 889 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); 890 891 // The following test code is disabled because SkProxyCanvas is 892 // missing a lot of virtual overrides on get* methods, which are used 893 // to verify canvas state. 894 // Issue: http://code.google.com/p/skia/issues/detail?id=500 895 896 if (false) { // avoid bit rot, suppress warning 897 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 898 } 899 900 // The following test code is disabled because SkNWayCanvas does not 901 // report correct clipping and device bounds information 902 // Issue: http://code.google.com/p/skia/issues/detail?id=501 903 904 if (false) { // avoid bit rot, suppress warning 905 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 906 } 907 908 if (false) { // avoid bit rot, suppress warning 909 test_clipVisitor(reporter, &referenceCanvas); 910 } 911 } 912 913 static void TestCanvas(skiatest::Reporter* reporter) { 914 // Init global here because bitmap pixels cannot be alocated during 915 // static initialization 916 kTestBitmap = testBitmap(); 917 918 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 919 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 920 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 921 testStepArray()[testStep], 0); 922 if (testStepArray()[testStep]->enablePdfTesting()) { 923 TestPdfDevice(reporter, testStepArray()[testStep]); 924 } 925 } 926 927 // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) 928 kTestBitmap.reset(); 929 } 930 931 #include "TestClassDef.h" 932 DEFINE_TESTCLASS("Canvas", TestCanvasClass, TestCanvas) 933