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