CanvasTest.cpp revision 385fe4d4b62d7d1dd76116dd570df3290a2f487b
1/* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8/* Description: 9 * This test defines a series of elementatry test steps that perform 10 * a single or a small group of canvas API calls. Each test step is 11 * used in several test cases that verify that different types of SkCanvas 12 * flavors and derivatives pass it and yield consistent behavior. The 13 * test cases analyse results that are queryable through the API. They do 14 * not look at rendering results. 15 * 16 * Adding test stepss: 17 * The general pattern for creating a new test step is to write a test 18 * function of the form: 19 * 20 * static void MyTestStepFunction(SkCanvas* canvas, 21 * skiatest::Reporter* reporter, 22 * CanvasTestStep* testStep) 23 * { 24 * canvas->someCanvasAPImethod(); 25 * (...) 26 * REPORTER_ASSERT_MESSAGE(reporter, (...), \ 27 * testStep->assertMessage()); 28 * } 29 * 30 * The definition of the test step function should be followed by an 31 * invocation of the TEST_STEP macro, which generates a class and 32 * instance for the test step: 33 * 34 * TEST_STEP(MyTestStep, MyTestStepFunction) 35 * 36 * There are also short hand macros for defining simple test steps 37 * in a single line of code. A simple test step is a one that is made 38 * of a single canvas API call. 39 * 40 * SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod()); 41 * 42 * There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that 43 * works the same way as SIMPLE_TEST_STEP, and additionally verifies 44 * that the invoked method returns a non-zero value. 45 */ 46#include "SkBitmap.h" 47#include "SkCanvas.h" 48#include "SkClipStack.h" 49#include "SkDevice.h" 50#include "SkDocument.h" 51#include "SkMatrix.h" 52#include "SkNWayCanvas.h" 53#include "SkPaint.h" 54#include "SkPaintFilterCanvas.h" 55#include "SkPath.h" 56#include "SkPicture.h" 57#include "SkPictureRecord.h" 58#include "SkPictureRecorder.h" 59#include "SkRect.h" 60#include "SkRegion.h" 61#include "SkShader.h" 62#include "SkStream.h" 63#include "SkSurface.h" 64#include "SkTDArray.h" 65#include "Test.h" 66 67static const int kWidth = 2, kHeight = 2; 68 69static void createBitmap(SkBitmap* bm, SkColor color) { 70 bm->allocN32Pixels(kWidth, kHeight); 71 bm->eraseColor(color); 72} 73 74/////////////////////////////////////////////////////////////////////////////// 75// Constants used by test steps 76const SkPoint kTestPoints[] = { 77 {SkIntToScalar(0), SkIntToScalar(0)}, 78 {SkIntToScalar(2), SkIntToScalar(1)}, 79 {SkIntToScalar(0), SkIntToScalar(2)} 80}; 81const SkPoint kTestPoints2[] = { 82 { SkIntToScalar(0), SkIntToScalar(1) }, 83 { SkIntToScalar(1), SkIntToScalar(1) }, 84 { SkIntToScalar(2), SkIntToScalar(1) }, 85 { SkIntToScalar(3), SkIntToScalar(1) }, 86 { SkIntToScalar(4), SkIntToScalar(1) }, 87 { SkIntToScalar(5), SkIntToScalar(1) }, 88 { SkIntToScalar(6), SkIntToScalar(1) }, 89 { SkIntToScalar(7), SkIntToScalar(1) }, 90 { SkIntToScalar(8), SkIntToScalar(1) }, 91 { SkIntToScalar(9), SkIntToScalar(1) }, 92 { SkIntToScalar(10), SkIntToScalar(1) } 93}; 94 95struct TestData { 96public: 97 TestData() 98 : fRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 99 SkIntToScalar(2), SkIntToScalar(1))) 100 , fMatrix(TestMatrix()) 101 , fPath(TestPath()) 102 , fNearlyZeroLengthPath(TestNearlyZeroLengthPath()) 103 , fIRect(SkIRect::MakeXYWH(0, 0, 2, 1)) 104 , fRegion(TestRegion()) 105 , fColor(0x01020304) 106 , fPoints(kTestPoints) 107 , fPointCount(3) 108 , fWidth(2) 109 , fHeight(2) 110 , fText("Hello World") 111 , fPoints2(kTestPoints2) 112 , fBitmap(TestBitmap()) 113 { } 114 115 SkRect fRect; 116 SkMatrix fMatrix; 117 SkPath fPath; 118 SkPath fNearlyZeroLengthPath; 119 SkIRect fIRect; 120 SkRegion fRegion; 121 SkColor fColor; 122 SkPaint fPaint; 123 const SkPoint* fPoints; 124 size_t fPointCount; 125 int fWidth; 126 int fHeight; 127 SkString fText; 128 const SkPoint* fPoints2; 129 SkBitmap fBitmap; 130 131private: 132 static SkMatrix TestMatrix() { 133 SkMatrix matrix; 134 matrix.reset(); 135 matrix.setScale(SkIntToScalar(2), SkIntToScalar(3)); 136 137 return matrix; 138 } 139 static SkPath TestPath() { 140 SkPath path; 141 path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 142 SkIntToScalar(2), SkIntToScalar(1))); 143 return path; 144 } 145 static SkPath TestNearlyZeroLengthPath() { 146 SkPath path; 147 SkPoint pt1 = { 0, 0 }; 148 SkPoint pt2 = { 0, SK_ScalarNearlyZero }; 149 SkPoint pt3 = { SkIntToScalar(1), 0 }; 150 SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; 151 path.moveTo(pt1); 152 path.lineTo(pt2); 153 path.lineTo(pt3); 154 path.lineTo(pt4); 155 return path; 156 } 157 static SkRegion TestRegion() { 158 SkRegion region; 159 SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1); 160 region.setRect(rect); 161 return region; 162 } 163 static SkBitmap TestBitmap() { 164 SkBitmap bitmap; 165 createBitmap(&bitmap, 0x05060708); 166 return bitmap; 167 } 168}; 169 170static bool equal_clips(const SkCanvas& a, const SkCanvas& b) { 171 if (a.isClipEmpty()) { 172 return b.isClipEmpty(); 173 } 174 if (!a.isClipRect()) { 175 // this is liberally true, since we don't expose a way to know this exactly (for non-rects) 176 return !b.isClipRect(); 177 } 178 SkIRect ar, br; 179 a.getClipDeviceBounds(&ar); 180 b.getClipDeviceBounds(&br); 181 return ar == br; 182} 183 184class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor { 185public: 186 Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {} 187 188 void clipRect(const SkRect& r, SkRegion::Op op, bool aa) override { 189 fTarget->clipRect(r, op, aa); 190 } 191 void clipRRect(const SkRRect& r, SkRegion::Op op, bool aa) override { 192 fTarget->clipRRect(r, op, aa); 193 } 194 void clipPath(const SkPath& p, SkRegion::Op op, bool aa) override { 195 fTarget->clipPath(p, op, aa); 196 } 197 198private: 199 SkCanvas* fTarget; 200}; 201 202static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) { 203 SkISize size = canvas->getDeviceSize(); 204 205 SkBitmap bm; 206 bm.setInfo(SkImageInfo::MakeN32Premul(size.width(), size.height())); 207 SkCanvas c(bm); 208 209 Canvas2CanvasClipVisitor visitor(&c); 210 canvas->replayClips(&visitor); 211 212 REPORTER_ASSERT(reporter, equal_clips(c, *canvas)); 213} 214 215static void test_clipstack(skiatest::Reporter* reporter) { 216 // The clipstack is refcounted, and needs to be able to out-live the canvas if a client has 217 // ref'd it. 218 const SkClipStack* cs = NULL; 219 { 220 SkCanvas canvas(10, 10); 221 cs = SkRef(canvas.getClipStack()); 222 } 223 REPORTER_ASSERT(reporter, cs->unique()); 224 cs->unref(); 225} 226 227// Format strings that describe the test context. The %s token is where 228// the name of the test step is inserted. The context is required for 229// disambiguating the error in the case of failures that are reported in 230// functions that are called multiple times in different contexts (test 231// cases and test steps). 232static const char* const kDefaultAssertMessageFormat = "%s"; 233static const char* const kCanvasDrawAssertMessageFormat = 234 "Drawing test step %s with SkCanvas"; 235static const char* const kNWayDrawAssertMessageFormat = 236 "Drawing test step %s with SkNWayCanvas"; 237static const char* const kNWayStateAssertMessageFormat = 238 "test step %s, SkNWayCanvas state consistency"; 239static const char* const kNWayIndirect1StateAssertMessageFormat = 240 "test step %s, SkNWayCanvas indirect canvas 1 state consistency"; 241static const char* const kNWayIndirect2StateAssertMessageFormat = 242 "test step %s, SkNWayCanvas indirect canvas 2 state consistency"; 243static const char* const kPdfAssertMessageFormat = 244 "PDF sanity check failed %s"; 245 246class CanvasTestStep; 247static SkTDArray<CanvasTestStep*>& testStepArray() { 248 static SkTDArray<CanvasTestStep*> theTests; 249 return theTests; 250} 251 252class CanvasTestStep { 253public: 254 CanvasTestStep(bool fEnablePdfTesting = true) { 255 *testStepArray().append() = this; 256 fAssertMessageFormat = kDefaultAssertMessageFormat; 257 this->fEnablePdfTesting = fEnablePdfTesting; 258 } 259 virtual ~CanvasTestStep() { } 260 261 virtual void draw(SkCanvas*, const TestData&, skiatest::Reporter*) = 0; 262 virtual const char* name() const = 0; 263 264 const char* assertMessage() { 265 fAssertMessage.printf(fAssertMessageFormat, name()); 266 return fAssertMessage.c_str(); 267 } 268 269 void setAssertMessageFormat(const char* format) { 270 fAssertMessageFormat = format; 271 } 272 273 bool enablePdfTesting() { return fEnablePdfTesting; } 274 275private: 276 SkString fAssertMessage; 277 const char* fAssertMessageFormat; 278 bool fEnablePdfTesting; 279}; 280 281/////////////////////////////////////////////////////////////////////////////// 282// Macros for defining test steps 283 284#define TEST_STEP(NAME, FUNCTION) \ 285class NAME##_TestStep : public CanvasTestStep{ \ 286public: \ 287 virtual void draw(SkCanvas* canvas, const TestData& d, \ 288 skiatest::Reporter* reporter) { \ 289 FUNCTION (canvas, d, reporter, this); \ 290 } \ 291 virtual const char* name() const {return #NAME ;} \ 292}; \ 293static NAME##_TestStep NAME##_TestStepInstance; 294 295#define TEST_STEP_NO_PDF(NAME, FUNCTION) \ 296class NAME##_TestStep : public CanvasTestStep{ \ 297public: \ 298 NAME##_TestStep() : CanvasTestStep(false) {} \ 299 virtual void draw(SkCanvas* canvas, const TestData& d, \ 300 skiatest::Reporter* reporter) { \ 301 FUNCTION (canvas, d, reporter, this); \ 302 } \ 303 virtual const char* name() const {return #NAME ;} \ 304}; \ 305static NAME##_TestStep NAME##_TestStepInstance; 306 307#define SIMPLE_TEST_STEP(NAME, CALL) \ 308static void NAME##TestStep(SkCanvas* canvas, const TestData& d, \ 309 skiatest::Reporter*, CanvasTestStep*) { \ 310 canvas-> CALL ; \ 311} \ 312TEST_STEP(NAME, NAME##TestStep ) 313 314#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL) \ 315static void NAME##TestStep(SkCanvas* canvas, const TestData& d, \ 316 skiatest::Reporter*, CanvasTestStep* testStep) { \ 317 REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL , \ 318 testStep->assertMessage()); \ 319} \ 320TEST_STEP(NAME, NAME##TestStep ) 321 322 323/////////////////////////////////////////////////////////////////////////////// 324// Basic test steps for most virtual methods in SkCanvas that draw or affect 325// the state of the canvas. 326 327SIMPLE_TEST_STEP(Translate, translate(SkIntToScalar(1), SkIntToScalar(2))); 328SIMPLE_TEST_STEP(Scale, scale(SkIntToScalar(1), SkIntToScalar(2))); 329SIMPLE_TEST_STEP(Rotate, rotate(SkIntToScalar(1))); 330SIMPLE_TEST_STEP(Skew, skew(SkIntToScalar(1), SkIntToScalar(2))); 331SIMPLE_TEST_STEP(Concat, concat(d.fMatrix)); 332SIMPLE_TEST_STEP(SetMatrix, setMatrix(d.fMatrix)); 333SIMPLE_TEST_STEP(ClipRect, clipRect(d.fRect)); 334SIMPLE_TEST_STEP(ClipPath, clipPath(d.fPath)); 335SIMPLE_TEST_STEP(ClipRegion, clipRegion(d.fRegion, SkRegion::kReplace_Op)); 336SIMPLE_TEST_STEP(Clear, clear(d.fColor)); 337 338/////////////////////////////////////////////////////////////////////////////// 339// Complex test steps 340 341static void SaveMatrixClipStep(SkCanvas* canvas, const TestData& d, 342 skiatest::Reporter* reporter, CanvasTestStep* testStep) { 343 int saveCount = canvas->getSaveCount(); 344 canvas->save(); 345 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 346 canvas->clipRegion(d.fRegion); 347 canvas->restore(); 348 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 349 testStep->assertMessage()); 350 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 351 testStep->assertMessage()); 352// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); 353} 354TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 355 356static void SaveLayerStep(SkCanvas* canvas, const TestData& d, 357 skiatest::Reporter* reporter, CanvasTestStep* testStep) { 358 int saveCount = canvas->getSaveCount(); 359 canvas->saveLayer(NULL, NULL); 360 canvas->restore(); 361 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 362 testStep->assertMessage()); 363} 364TEST_STEP(SaveLayer, SaveLayerStep); 365 366static void BoundedSaveLayerStep(SkCanvas* canvas, const TestData& d, 367 skiatest::Reporter* reporter, CanvasTestStep* testStep) { 368 int saveCount = canvas->getSaveCount(); 369 canvas->saveLayer(&d.fRect, NULL); 370 canvas->restore(); 371 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 372 testStep->assertMessage()); 373} 374TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 375 376static void PaintSaveLayerStep(SkCanvas* canvas, const TestData& d, 377 skiatest::Reporter* reporter, CanvasTestStep* testStep) { 378 int saveCount = canvas->getSaveCount(); 379 canvas->saveLayer(NULL, &d.fPaint); 380 canvas->restore(); 381 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 382 testStep->assertMessage()); 383} 384TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 385 386static void TwoClipOpsStep(SkCanvas* canvas, const TestData& d, 387 skiatest::Reporter*, CanvasTestStep*) { 388 // This test exercises a functionality in SkPicture that leads to the 389 // recording of restore offset placeholders. This test will trigger an 390 // assertion at playback time if the placeholders are not properly 391 // filled when the recording ends. 392 canvas->clipRect(d.fRect); 393 canvas->clipRegion(d.fRegion); 394} 395TEST_STEP(TwoClipOps, TwoClipOpsStep); 396 397// exercise fix for http://code.google.com/p/skia/issues/detail?id=560 398// ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 399static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, const TestData& d, 400 skiatest::Reporter*, CanvasTestStep*) { 401 SkPaint paint; 402 paint.setStrokeWidth(SkIntToScalar(1)); 403 paint.setStyle(SkPaint::kStroke_Style); 404 405 canvas->drawPath(d.fNearlyZeroLengthPath, paint); 406} 407TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 408 409static void DrawVerticesShaderTestStep(SkCanvas* canvas, const TestData& d, 410 skiatest::Reporter*, CanvasTestStep*) { 411 SkPoint pts[4]; 412 pts[0].set(0, 0); 413 pts[1].set(SkIntToScalar(d.fWidth), 0); 414 pts[2].set(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight)); 415 pts[3].set(0, SkIntToScalar(d.fHeight)); 416 SkPaint paint; 417 SkShader* shader = SkShader::CreateBitmapShader(d.fBitmap, 418 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 419 paint.setShader(shader)->unref(); 420 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 421 NULL, NULL, NULL, 0, paint); 422} 423// NYI: issue 240. 424TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); 425 426static void DrawPictureTestStep(SkCanvas* canvas, const TestData& d, 427 skiatest::Reporter*, CanvasTestStep*) { 428 SkPictureRecorder recorder; 429 SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight), 430 NULL, 0); 431 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 432 testCanvas->clipRect(d.fRect); 433 testCanvas->drawRect(d.fRect, d.fPaint); 434 SkAutoTUnref<SkPicture> testPicture(recorder.endRecording()); 435 436 canvas->drawPicture(testPicture); 437} 438TEST_STEP(DrawPicture, DrawPictureTestStep); 439 440static void SaveRestoreTestStep(SkCanvas* canvas, const TestData& d, 441 skiatest::Reporter* reporter, CanvasTestStep* testStep) { 442 int baseSaveCount = canvas->getSaveCount(); 443 int n = canvas->save(); 444 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 445 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 446 testStep->assertMessage()); 447 canvas->save(); 448 canvas->save(); 449 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 450 testStep->assertMessage()); 451 canvas->restoreToCount(baseSaveCount + 1); 452 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 453 testStep->assertMessage()); 454 455 // should this pin to 1, or be a no-op, or crash? 456 canvas->restoreToCount(0); 457 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 458 testStep->assertMessage()); 459} 460TEST_STEP(SaveRestore, SaveRestoreTestStep); 461 462static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, const TestData& d, 463 skiatest::Reporter*, CanvasTestStep*) { 464 // This test step challenges the TestDeferredCanvasStateConsistency 465 // test cases because the opaque paint can trigger an optimization 466 // that discards previously recorded commands. The challenge is to maintain 467 // correct clip and matrix stack state. 468 canvas->resetMatrix(); 469 canvas->rotate(SkIntToScalar(30)); 470 canvas->save(); 471 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 472 canvas->save(); 473 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 474 SkPaint paint; 475 paint.setColor(0xFFFFFFFF); 476 canvas->drawPaint(paint); 477 canvas->restore(); 478 canvas->restore(); 479} 480TEST_STEP(NestedSaveRestoreWithSolidPaint, \ 481 NestedSaveRestoreWithSolidPaintTestStep); 482 483static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, const TestData& d, 484 skiatest::Reporter*, CanvasTestStep*) { 485 // This test step challenges the TestDeferredCanvasStateConsistency 486 // test case because the canvas flush on a deferred canvas will 487 // reset the recording session. The challenge is to maintain correct 488 // clip and matrix stack state on the playback canvas. 489 canvas->resetMatrix(); 490 canvas->rotate(SkIntToScalar(30)); 491 canvas->save(); 492 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 493 canvas->save(); 494 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 495 canvas->drawRect(d.fRect,d.fPaint); 496 canvas->flush(); 497 canvas->restore(); 498 canvas->restore(); 499} 500TEST_STEP(NestedSaveRestoreWithFlush, NestedSaveRestoreWithFlushTestStep); 501 502static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, const TestData& d, 503 const SkCanvas* canvas1, const SkCanvas* canvas2, 504 CanvasTestStep* testStep) { 505 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 506 canvas2->getDeviceSize(), testStep->assertMessage()); 507 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 508 canvas2->getSaveCount(), testStep->assertMessage()); 509 510 SkRect bounds1, bounds2; 511 REPORTER_ASSERT_MESSAGE(reporter, 512 canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), 513 testStep->assertMessage()); 514 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 515 testStep->assertMessage()); 516 517 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 518 canvas2->getDrawFilter(), testStep->assertMessage()); 519 SkIRect deviceBounds1, deviceBounds2; 520 REPORTER_ASSERT_MESSAGE(reporter, 521 canvas1->getClipDeviceBounds(&deviceBounds1) == 522 canvas2->getClipDeviceBounds(&deviceBounds2), 523 testStep->assertMessage()); 524 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, testStep->assertMessage()); 525 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 526 canvas2->getTotalMatrix(), testStep->assertMessage()); 527 REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage()); 528 529 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 530 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 531 while (!layerIter1.done() && !layerIter2.done()) { 532 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 533 layerIter2.matrix(), testStep->assertMessage()); 534 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 535 layerIter2.clip(), testStep->assertMessage()); 536 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 537 layerIter2.paint(), testStep->assertMessage()); 538 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 539 layerIter2.x(), testStep->assertMessage()); 540 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 541 layerIter2.y(), testStep->assertMessage()); 542 layerIter1.next(); 543 layerIter2.next(); 544 } 545 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 546 testStep->assertMessage()); 547 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 548 testStep->assertMessage()); 549 550} 551 552static void TestPdfDevice(skiatest::Reporter* reporter, 553 const TestData& d, 554 CanvasTestStep* testStep) { 555 SkDynamicMemoryWStream outStream; 556 SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream)); 557#if SK_SUPPORT_PDF 558 REPORTER_ASSERT(reporter, doc); 559#else 560 REPORTER_ASSERT(reporter, !doc); 561#endif // SK_SUPPORT_PDF 562 if (!doc) { 563 return; 564 } 565 SkCanvas* canvas = doc->beginPage(SkIntToScalar(d.fWidth), 566 SkIntToScalar(d.fHeight)); 567 REPORTER_ASSERT(reporter, canvas); 568 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 569 testStep->draw(canvas, d, reporter); 570 571 REPORTER_ASSERT(reporter, doc->close()); 572} 573 574// unused 575static void TestNWayCanvasStateConsistency( 576 skiatest::Reporter* reporter, 577 const TestData& d, 578 CanvasTestStep* testStep, 579 const SkCanvas& referenceCanvas) { 580 581 SkBitmap indirectStore1; 582 createBitmap(&indirectStore1, 0xFFFFFFFF); 583 SkCanvas indirectCanvas1(indirectStore1); 584 585 SkBitmap indirectStore2; 586 createBitmap(&indirectStore2, 0xFFFFFFFF); 587 SkCanvas indirectCanvas2(indirectStore2); 588 589 SkISize canvasSize = referenceCanvas.getDeviceSize(); 590 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 591 nWayCanvas.addCanvas(&indirectCanvas1); 592 nWayCanvas.addCanvas(&indirectCanvas2); 593 594 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 595 testStep->draw(&nWayCanvas, d, reporter); 596 // Verify that the SkNWayCanvas reports consitent state 597 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 598 AssertCanvasStatesEqual(reporter, d, &nWayCanvas, &referenceCanvas, testStep); 599 // Verify that the indirect canvases report consitent state 600 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 601 AssertCanvasStatesEqual(reporter, d, &indirectCanvas1, &referenceCanvas, testStep); 602 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 603 AssertCanvasStatesEqual(reporter, d, &indirectCanvas2, &referenceCanvas, testStep); 604} 605 606/* 607 * This sub-test verifies that the test step passes when executed 608 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 609 * that the all canvas derivatives report the same state as an SkCanvas 610 * after having executed the test step. 611 */ 612static void TestOverrideStateConsistency(skiatest::Reporter* reporter, const TestData& d, 613 CanvasTestStep* testStep) { 614 SkBitmap referenceStore; 615 createBitmap(&referenceStore, 0xFFFFFFFF); 616 SkCanvas referenceCanvas(referenceStore); 617 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 618 testStep->draw(&referenceCanvas, d, reporter); 619 620 // The following test code is disabled because SkNWayCanvas does not 621 // report correct clipping and device bounds information 622 // Issue: http://code.google.com/p/skia/issues/detail?id=501 623 624 if (false) { // avoid bit rot, suppress warning 625 TestNWayCanvasStateConsistency(reporter, d, testStep, referenceCanvas); 626 } 627 628 if (false) { // avoid bit rot, suppress warning 629 test_clipVisitor(reporter, &referenceCanvas); 630 } 631 test_clipstack(reporter); 632} 633 634static void test_newraster(skiatest::Reporter* reporter) { 635 SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 636 const size_t minRowBytes = info.minRowBytes(); 637 const size_t size = info.getSafeSize(minRowBytes); 638 SkAutoMalloc storage(size); 639 SkPMColor* baseAddr = static_cast<SkPMColor*>(storage.get()); 640 sk_bzero(baseAddr, size); 641 642 SkCanvas* canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes); 643 REPORTER_ASSERT(reporter, canvas); 644 645 SkImageInfo info2; 646 size_t rowBytes; 647 const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); 648 REPORTER_ASSERT(reporter, addr); 649 REPORTER_ASSERT(reporter, info == info2); 650 REPORTER_ASSERT(reporter, minRowBytes == rowBytes); 651 for (int y = 0; y < info.height(); ++y) { 652 for (int x = 0; x < info.width(); ++x) { 653 REPORTER_ASSERT(reporter, 0 == addr[x]); 654 } 655 addr = (const SkPMColor*)((const char*)addr + rowBytes); 656 } 657 delete canvas; 658 659 // now try a deliberately bad info 660 info = info.makeWH(-1, info.height()); 661 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes)); 662 663 // too big 664 info = info.makeWH(1 << 30, 1 << 30); 665 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes)); 666 667 // not a valid pixel type 668 info = SkImageInfo::Make(10, 10, kUnknown_SkColorType, info.alphaType()); 669 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes)); 670 671 // We should succeed with a zero-sized valid info 672 info = SkImageInfo::MakeN32Premul(0, 0); 673 canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes); 674 REPORTER_ASSERT(reporter, canvas); 675 delete canvas; 676} 677 678DEF_TEST(Canvas, reporter) { 679 TestData d; 680 681 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 682 TestOverrideStateConsistency(reporter, d, testStepArray()[testStep]); 683 if (testStepArray()[testStep]->enablePdfTesting()) { 684 TestPdfDevice(reporter, d, testStepArray()[testStep]); 685 } 686 } 687 688 test_newraster(reporter); 689} 690 691DEF_TEST(Canvas_SaveState, reporter) { 692 SkCanvas canvas(10, 10); 693 REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount()); 694 695 int n = canvas.save(); 696 REPORTER_ASSERT(reporter, 1 == n); 697 REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount()); 698 699 n = canvas.saveLayer(NULL, NULL); 700 REPORTER_ASSERT(reporter, 2 == n); 701 REPORTER_ASSERT(reporter, 3 == canvas.getSaveCount()); 702 703 canvas.restore(); 704 REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount()); 705 canvas.restore(); 706 REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount()); 707} 708 709DEF_TEST(Canvas_ClipEmptyPath, reporter) { 710 SkCanvas canvas(10, 10); 711 canvas.save(); 712 SkPath path; 713 canvas.clipPath(path); 714 canvas.restore(); 715 canvas.save(); 716 path.moveTo(5, 5); 717 canvas.clipPath(path); 718 canvas.restore(); 719 canvas.save(); 720 path.moveTo(7, 7); 721 canvas.clipPath(path); // should not assert here 722 canvas.restore(); 723} 724 725namespace { 726 727class MockFilterCanvas : public SkPaintFilterCanvas { 728public: 729 MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { } 730 731protected: 732 void onFilterPaint(SkPaint *paint, Type type) const override { } 733 734private: 735 typedef SkPaintFilterCanvas INHERITED; 736}; 737 738} // anonymous namespace 739 740// SkPaintFilterCanvas should inherit the initial target canvas state. 741DEF_TEST(PaintFilterCanvas_ConsistentState, reporter) { 742 SkCanvas canvas(100, 100); 743 canvas.clipRect(SkRect::MakeXYWH(12.7f, 12.7f, 75, 75)); 744 canvas.scale(0.5f, 0.75f); 745 746 SkRect clip1, clip2; 747 748 MockFilterCanvas filterCanvas(&canvas); 749 REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix()); 750 REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2)); 751 REPORTER_ASSERT(reporter, clip1 == clip2); 752 753 filterCanvas.clipRect(SkRect::MakeXYWH(30.5f, 30.7f, 100, 100)); 754 filterCanvas.scale(0.75f, 0.5f); 755 REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix()); 756 REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2)); 757 REPORTER_ASSERT(reporter, clip1 == clip2); 758} 759