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