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