CanvasTest.cpp revision 4e6dfa51525e174d79cb88800d8e5f2c88291270
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 kTestPoints2[] = { 222 { SkIntToScalar(0), SkIntToScalar(1) }, 223 { SkIntToScalar(1), SkIntToScalar(1) }, 224 { SkIntToScalar(2), SkIntToScalar(1) }, 225 { SkIntToScalar(3), SkIntToScalar(1) }, 226 { SkIntToScalar(4), SkIntToScalar(1) }, 227 { SkIntToScalar(5), SkIntToScalar(1) }, 228 { SkIntToScalar(6), SkIntToScalar(1) }, 229 { SkIntToScalar(7), SkIntToScalar(1) }, 230 { SkIntToScalar(8), SkIntToScalar(1) }, 231 { SkIntToScalar(9), SkIntToScalar(1) }, 232 { SkIntToScalar(10), SkIntToScalar(1) }, 233}; 234 235 236/////////////////////////////////////////////////////////////////////////////// 237// Macros for defining test steps 238 239#define TEST_STEP(NAME, FUNCTION) \ 240class NAME##_TestStep : public CanvasTestStep{ \ 241public: \ 242 virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ 243 FUNCTION (canvas, reporter, this); \ 244 } \ 245 virtual const char* name() const {return #NAME ;} \ 246}; \ 247static NAME##_TestStep NAME##_TestStepInstance; 248 249#define SIMPLE_TEST_STEP(NAME, CALL) \ 250static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \ 251 CanvasTestStep*) { \ 252 canvas-> CALL ; \ 253} \ 254TEST_STEP(NAME, NAME##TestStep ) 255 256#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL) \ 257static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \ 258 CanvasTestStep* testStep) { \ 259 REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL , \ 260 testStep->assertMessage()); \ 261} \ 262TEST_STEP(NAME, NAME##TestStep ) 263 264 265/////////////////////////////////////////////////////////////////////////////// 266// Basic test steps for most virtual methods in SkCanvas that draw or affect 267// the state of the canvas. 268 269SIMPLE_TEST_STEP_WITH_ASSERT(Translate, 270 translate(SkIntToScalar(1), SkIntToScalar(2))); 271SIMPLE_TEST_STEP_WITH_ASSERT(Scale, 272 scale(SkIntToScalar(1), SkIntToScalar(2))); 273SIMPLE_TEST_STEP_WITH_ASSERT(Rotate, rotate(SkIntToScalar(1))); 274SIMPLE_TEST_STEP_WITH_ASSERT(Skew, 275 skew(SkIntToScalar(1), SkIntToScalar(2))); 276SIMPLE_TEST_STEP_WITH_ASSERT(Concat, concat(kTestMatrix)); 277SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix)); 278SIMPLE_TEST_STEP(ClipRect, clipRect(kTestRect)); 279SIMPLE_TEST_STEP(ClipPath, clipPath(kTestPath)); 280SIMPLE_TEST_STEP(ClipRegion, 281 clipRegion(kTestRegion, SkRegion::kReplace_Op)); 282SIMPLE_TEST_STEP(Clear, clear(kTestColor)); 283SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint)); 284SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode, 285 kTestPointCount, kTestPoints, kTestPaint)); 286SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode, 287 kTestPointCount, kTestPoints, kTestPaint)); 288SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode, 289 kTestPointCount, kTestPoints, kTestPaint)); 290SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint)); 291SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint)); 292SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0)); 293SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint)); 294SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect, 295 NULL)); 296SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap, 297 &kTestIRect, kTestRect, NULL)); 298SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL, 299 kTestRect, &kTestPaint)); 300SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix, 301 NULL)); 302SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap, 303 kTestMatrix, &kTestPaint)); 304SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect, 305 kTestRect, NULL)); 306SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect, 307 kTestRect, &kTestPaint)); 308SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL)); 309SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint)); 310SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(), 311 0, 1, kTestPaint)); 312SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(), 313 kTestText.size(), kTestPoints2, kTestPaint)); 314SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(), 315 kTestText.size(), kTestPath, NULL, kTestPaint)); 316SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(), 317 kTestText.size(), kTestPath, &kTestMatrix, kTestPaint)); 318SIMPLE_TEST_STEP(SetExternalMatrix, setExternalMatrix(&kTestMatrix)); 319SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size())); 320 321/////////////////////////////////////////////////////////////////////////////// 322// Complex test steps 323 324// Save/restore calls cannot be in isolated simple test steps because the test 325// cases that use SkPicture require that save and restore calls be balanced. 326static void SaveMatrixStep(SkCanvas* canvas, 327 skiatest::Reporter* reporter, 328 CanvasTestStep* testStep) { 329 int saveCount = canvas->getSaveCount(); 330 canvas->save(SkCanvas::kMatrix_SaveFlag); 331 canvas->clipRegion(kTestRegion); 332 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 333 canvas->restore(); 334 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 335 testStep->assertMessage()); 336 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 337 testStep->assertMessage()); 338 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() == kTestRegion, 339 testStep->assertMessage()); 340} 341TEST_STEP(SaveMatrix, SaveMatrixStep); 342 343static void SaveClipStep(SkCanvas* canvas, 344 skiatest::Reporter* reporter, 345 CanvasTestStep* testStep) { 346 int saveCount = canvas->getSaveCount(); 347 canvas->save(SkCanvas::kClip_SaveFlag); 348 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 349 canvas->clipRegion(kTestRegion); 350 canvas->restore(); 351 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 352 testStep->assertMessage()); 353 REPORTER_ASSERT_MESSAGE(reporter, !canvas->getTotalMatrix().isIdentity(), 354 testStep->assertMessage()); 355 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 356 testStep->assertMessage()); 357} 358TEST_STEP(SaveClip, SaveClipStep); 359 360static void SaveMatrixClipStep(SkCanvas* canvas, 361 skiatest::Reporter* reporter, 362 CanvasTestStep* testStep) { 363 int saveCount = canvas->getSaveCount(); 364 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 365 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 366 canvas->clipRegion(kTestRegion); 367 canvas->restore(); 368 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 369 testStep->assertMessage()); 370 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 371 testStep->assertMessage()); 372 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, 373 testStep->assertMessage()); 374} 375TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 376 377static void SaveLayerStep(SkCanvas* canvas, 378 skiatest::Reporter* reporter, 379 CanvasTestStep* testStep) { 380 int saveCount = canvas->getSaveCount(); 381 canvas->saveLayer(NULL, NULL); 382 canvas->restore(); 383 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 384 testStep->assertMessage()); 385} 386TEST_STEP(SaveLayer, SaveLayerStep); 387 388static void BoundedSaveLayerStep(SkCanvas* canvas, 389 skiatest::Reporter* reporter, 390 CanvasTestStep* testStep) { 391 int saveCount = canvas->getSaveCount(); 392 canvas->saveLayer(&kTestRect, NULL); 393 canvas->restore(); 394 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 395 testStep->assertMessage()); 396} 397TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 398 399static void PaintSaveLayerStep(SkCanvas* canvas, 400 skiatest::Reporter* reporter, 401 CanvasTestStep* testStep) { 402 int saveCount = canvas->getSaveCount(); 403 canvas->saveLayer(NULL, &kTestPaint); 404 canvas->restore(); 405 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 406 testStep->assertMessage()); 407} 408TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 409 410static void TwoClipOpsStep(SkCanvas* canvas, 411 skiatest::Reporter* reporter, 412 CanvasTestStep* testStep) { 413 // This test exercises a functionality in SkPicture that leads to the 414 // recording of restore offset placeholders. This test will trigger an 415 // assertion at playback time if the placeholders are not properly 416 // filled when the recording ends. 417 canvas->clipRect(kTestRect); 418 canvas->clipRegion(kTestRegion); 419} 420TEST_STEP(TwoClipOps, TwoClipOpsStep); 421 422// exercise fix for http://code.google.com/p/skia/issues/detail?id=560 423// ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 424static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, 425 skiatest::Reporter* reporter, 426 CanvasTestStep* testStep) { 427 SkPaint paint; 428 paint.setStrokeWidth(SkIntToScalar(1)); 429 paint.setStyle(SkPaint::kStroke_Style); 430 431 SkPath path; 432 SkPoint pt1 = { 0, 0 }; 433 SkPoint pt2 = { 0, SK_ScalarNearlyZero }; 434 SkPoint pt3 = { SkIntToScalar(1), 0 }; 435 SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; 436 path.moveTo(pt1); 437 path.lineTo(pt2); 438 path.lineTo(pt3); 439 path.lineTo(pt4); 440 441 canvas->drawPath(path, paint); 442} 443TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 444 445static void DrawVerticesShaderTestStep(SkCanvas* canvas, 446 skiatest::Reporter* reporter, 447 CanvasTestStep* testStep) { 448 SkPoint pts[4]; 449 pts[0].set(0, 0); 450 pts[1].set(SkIntToScalar(kWidth), 0); 451 pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 452 pts[3].set(0, SkIntToScalar(kHeight)); 453 SkPaint paint; 454 SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, 455 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 456 paint.setShader(shader)->unref(); 457 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 458 NULL, NULL, NULL, 0, paint); 459} 460TEST_STEP(DrawVerticesShader, DrawVerticesShaderTestStep); 461 462static void DrawPictureTestStep(SkCanvas* canvas, 463 skiatest::Reporter* reporter, 464 CanvasTestStep* testStep) { 465 SkPicture* testPicture = SkNEW_ARGS(SkPicture, ()); 466 SkAutoUnref aup(testPicture); 467 SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight); 468 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 469 testCanvas->clipRect(kTestRect); 470 testCanvas->drawRect(kTestRect, kTestPaint); 471 canvas->drawPicture(*testPicture); 472} 473TEST_STEP(DrawPicture, DrawPictureTestStep); 474 475static void SaveRestoreTestStep(SkCanvas* canvas, 476 skiatest::Reporter* reporter, 477 CanvasTestStep* testStep) { 478 int baseSaveCount = canvas->getSaveCount(); 479 size_t n = canvas->save(); 480 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 481 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 482 testStep->assertMessage()); 483 canvas->save(); 484 canvas->save(); 485 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 486 testStep->assertMessage()); 487 canvas->restoreToCount(baseSaveCount + 1); 488 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 489 testStep->assertMessage()); 490 491 // should this pin to 1, or be a no-op, or crash? 492 canvas->restoreToCount(0); 493 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 494 testStep->assertMessage()); 495} 496TEST_STEP(SaveRestore, SaveRestoreTestStep); 497 498static void DrawLayerTestStep(SkCanvas* canvas, 499 skiatest::Reporter* reporter, 500 CanvasTestStep* testStep) { 501 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 502 testStep->assertMessage()); 503 canvas->save(); 504 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 505 testStep->assertMessage()); 506 canvas->restore(); 507 508 const SkRect* bounds = NULL; // null means include entire bounds 509 const SkPaint* paint = NULL; 510 511 canvas->saveLayer(bounds, paint); 512 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 513 testStep->assertMessage()); 514 canvas->restore(); 515 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 516 testStep->assertMessage()); 517 518 canvas->saveLayer(bounds, paint); 519 canvas->saveLayer(bounds, paint); 520 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 521 testStep->assertMessage()); 522 canvas->restore(); 523 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 524 testStep->assertMessage()); 525 canvas->restore(); 526 // now layer count should be 0 527 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 528 testStep->assertMessage()); 529} 530TEST_STEP(DrawLayer, DrawLayerTestStep); 531 532static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, 533 const SkCanvas* canvas1, 534 const SkCanvas* canvas2, 535 CanvasTestStep* testStep) { 536 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 537 canvas2->getDeviceSize(), testStep->assertMessage()); 538 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 539 canvas2->getSaveCount(), testStep->assertMessage()); 540 REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == 541 canvas2->isDrawingToLayer(), testStep->assertMessage()); 542 SkRect bounds1, bounds2; 543 REPORTER_ASSERT_MESSAGE(reporter, 544 canvas1->getClipBounds(&bounds1, SkCanvas::kAA_EdgeType) == 545 canvas2->getClipBounds(&bounds2, SkCanvas::kAA_EdgeType), 546 testStep->assertMessage()); 547 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 548 testStep->assertMessage()); 549 REPORTER_ASSERT_MESSAGE(reporter, 550 canvas1->getClipBounds(&bounds1, SkCanvas::kBW_EdgeType) == 551 canvas2->getClipBounds(&bounds2, SkCanvas::kBW_EdgeType), 552 testStep->assertMessage()); 553 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 554 testStep->assertMessage()); 555 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 556 canvas2->getDrawFilter(), testStep->assertMessage()); 557 SkIRect deviceBounds1, deviceBounds2; 558 REPORTER_ASSERT_MESSAGE(reporter, 559 canvas1->getClipDeviceBounds(&deviceBounds1) == 560 canvas2->getClipDeviceBounds(&deviceBounds2), 561 testStep->assertMessage()); 562 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, 563 testStep->assertMessage()); 564 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 565 canvas2->getBounder(), testStep->assertMessage()); 566 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 567 canvas2->getTotalMatrix(), testStep->assertMessage()); 568 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getClipType() == 569 canvas2->getClipType(), testStep->assertMessage()); 570 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() == 571 canvas2->getTotalClip(), testStep->assertMessage()); 572 573 // The following test code is commented out because the test fails when 574 // the canvas is an SkPictureRecord or SkDeferredCanvas 575 // Issue: http://code.google.com/p/skia/issues/detail?id=498 576 // Also, creating a LayerIter on an SkProxyCanvas crashes 577 // Issue: http://code.google.com/p/skia/issues/detail?id=499 578 /* 579 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 580 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 581 while (!layerIter1.done() && !layerIter2.done()) { 582 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 583 layerIter2.matrix(), testStep->assertMessage()); 584 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 585 layerIter2.clip(), testStep->assertMessage()); 586 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 587 layerIter2.paint(), testStep->assertMessage()); 588 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 589 layerIter2.x(), testStep->assertMessage()); 590 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 591 layerIter2.y(), testStep->assertMessage()); 592 layerIter1.next(); 593 layerIter2.next(); 594 } 595 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 596 testStep->assertMessage()); 597 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 598 testStep->assertMessage()); 599 */ 600} 601 602// The following class groups static functions that need to access 603// the privates members of SkPictureRecord 604class SkPictureTester { 605private: 606 static int EQ(const SkFlatData* a, const SkFlatData* b) { 607 return *a == *b; 608 } 609 610 static void AssertFlattenedObjectsEqual( 611 SkPictureRecord* referenceRecord, 612 SkPictureRecord* testRecord, 613 skiatest::Reporter* reporter, 614 CanvasTestStep* testStep) { 615 616 REPORTER_ASSERT_MESSAGE(reporter, 617 referenceRecord->fBitmaps.count() == 618 testRecord->fBitmaps.count(), testStep->assertMessage()); 619 for (int i = 0; i < referenceRecord->fBitmaps.count(); ++i) { 620 REPORTER_ASSERT_MESSAGE(reporter, 621 EQ(referenceRecord->fBitmaps[i], testRecord->fBitmaps[i]), 622 testStep->assertMessage()); 623 } 624 REPORTER_ASSERT_MESSAGE(reporter, 625 referenceRecord->fMatrices.count() == 626 testRecord->fMatrices.count(), testStep->assertMessage()); 627 for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) { 628 REPORTER_ASSERT_MESSAGE(reporter, 629 EQ(referenceRecord->fMatrices[i], testRecord->fMatrices[i]), 630 testStep->assertMessage()); 631 } 632 REPORTER_ASSERT_MESSAGE(reporter, 633 referenceRecord->fPaints.count() == 634 testRecord->fPaints.count(), testStep->assertMessage()); 635 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 636 REPORTER_ASSERT_MESSAGE(reporter, 637 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 638 testStep->assertMessage()); 639 } 640 REPORTER_ASSERT_MESSAGE(reporter, 641 referenceRecord->fRegions.count() == 642 testRecord->fRegions.count(), testStep->assertMessage()); 643 for (int i = 0; i < referenceRecord->fRegions.count(); ++i) { 644 REPORTER_ASSERT_MESSAGE(reporter, 645 EQ(referenceRecord->fRegions[i], testRecord->fRegions[i]), 646 testStep->assertMessage()); 647 } 648 REPORTER_ASSERT_MESSAGE(reporter, 649 !referenceRecord->fPathHeap == 650 !testRecord->fPathHeap, 651 testStep->assertMessage()); 652 // The following tests are commented out because they currently 653 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 654 /* 655 if (referenceRecord->fPathHeap) { 656 REPORTER_ASSERT_MESSAGE(reporter, 657 referenceRecord->fPathHeap->count() == 658 testRecord->fPathHeap->count(), 659 testStep->assertMessage()); 660 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 661 REPORTER_ASSERT_MESSAGE(reporter, 662 (*referenceRecord->fPathHeap)[i] == 663 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 664 } 665 } 666 */ 667 668 } 669 670public: 671 672 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 673 CanvasTestStep* testStep, 674 uint32_t recordFlags) { 675 // Verify that when a test step is executed twice, no extra resources 676 // are flattened during the second execution 677 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 678 SkPicture referencePicture; 679 SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth, 680 kHeight, recordFlags); 681 testStep->draw(referenceCanvas, reporter); 682 SkPicture testPicture; 683 SkCanvas* testCanvas = testPicture.beginRecording(kWidth, 684 kHeight, recordFlags); 685 testStep->draw(testCanvas, reporter); 686 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 687 testStep->draw(testCanvas, reporter); 688 689 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>( 690 referenceCanvas); 691 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>( 692 testCanvas); 693 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 694 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 695 reporter, testStep); 696 } 697}; 698 699static void TestDeferredCanvasStateConsistency( 700 skiatest::Reporter* reporter, 701 CanvasTestStep* testStep, 702 const SkCanvas& referenceCanvas) { 703 704 SkBitmap deferredStore; 705 createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 706 SkDevice deferredDevice(deferredStore); 707 SkDeferredCanvas deferredCanvas(&deferredDevice); 708 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 709 testStep->draw(&deferredCanvas, reporter); 710 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 711 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 712 testStep); 713 714 // Verified that deferred canvas state is not affected by flushing 715 // pending draw operations 716 717 // The following test code is commented out because it currently fails. 718 // Issue: http://code.google.com/p/skia/issues/detail?id=496 719 /* 720 deferredCanvas.flush(); 721 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 722 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 723 testStep); 724 */ 725} 726 727// unused 728static void TestProxyCanvasStateConsistency( 729 skiatest::Reporter* reporter, 730 CanvasTestStep* testStep, 731 const SkCanvas& referenceCanvas) { 732 733 SkBitmap indirectStore; 734 createBitmap(&indirectStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 735 SkDevice indirectDevice(indirectStore); 736 SkCanvas indirectCanvas(&indirectDevice); 737 SkProxyCanvas proxyCanvas(&indirectCanvas); 738 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 739 testStep->draw(&proxyCanvas, reporter); 740 // Verify that the SkProxyCanvas reports consitent state 741 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 742 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 743 testStep); 744 // Verify that the indirect canvas reports consitent state 745 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 746 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 747 testStep); 748} 749 750// unused 751static void TestNWayCanvasStateConsistency( 752 skiatest::Reporter* reporter, 753 CanvasTestStep* testStep, 754 const SkCanvas& referenceCanvas) { 755 756 SkBitmap indirectStore1; 757 createBitmap(&indirectStore1, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 758 SkDevice indirectDevice1(indirectStore1); 759 SkCanvas indirectCanvas1(&indirectDevice1); 760 761 SkBitmap indirectStore2; 762 createBitmap(&indirectStore2, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 763 SkDevice indirectDevice2(indirectStore2); 764 SkCanvas indirectCanvas2(&indirectDevice2); 765 766 SkISize canvasSize = referenceCanvas.getDeviceSize(); 767 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 768 nWayCanvas.addCanvas(&indirectCanvas1); 769 nWayCanvas.addCanvas(&indirectCanvas2); 770 771 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 772 testStep->draw(&nWayCanvas, reporter); 773 // Verify that the SkProxyCanvas reports consitent state 774 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 775 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 776 testStep); 777 // Verify that the indirect canvases report consitent state 778 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 779 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 780 testStep); 781 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 782 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 783 testStep); 784} 785 786/* 787 * This sub-test verifies that the test step passes when executed 788 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 789 * that the all canvas derivatives report the same state as an SkCanvas 790 * after having executed the test step. 791 */ 792static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 793 CanvasTestStep* testStep) { 794 SkBitmap referenceStore; 795 createBitmap(&referenceStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF); 796 SkDevice referenceDevice(referenceStore); 797 SkCanvas referenceCanvas(&referenceDevice); 798 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 799 testStep->draw(&referenceCanvas, reporter); 800 801 TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas); 802 803 // The following test code is disabled because SkProxyCanvas is 804 // missing a lot of virtual overrides on get* methods, which are used 805 // to verify canvas state. 806 // Issue: http://code.google.com/p/skia/issues/detail?id=500 807 808 if (false) { // avoid bit rot, suppress warning 809 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 810 } 811 812 // The following test code is disabled because SkNWayCanvas does not 813 // report correct clipping and device bounds information 814 // Issue: http://code.google.com/p/skia/issues/detail?id=501 815 816 if (false) { // avoid bit rot, suppress warning 817 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 818 } 819 820 if (false) { // avoid bit rot, suppress warning 821 test_clipVisitor(reporter, &referenceCanvas); 822 } 823} 824 825static void TestCanvas(skiatest::Reporter* reporter) { 826 // Init global here because bitmap pixels cannot be alocated during 827 // static initialization 828 kTestBitmap = testBitmap(); 829 830 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 831 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 832 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 833 testStepArray()[testStep], 0); 834 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 835 testStepArray()[testStep], 836 SkPicture::kFlattenMutableNonTexturePixelRefs_RecordingFlag); 837 } 838} 839 840#include "TestClassDef.h" 841DEFINE_TESTCLASS("Canvas", TestCanvasClass, TestCanvas) 842