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