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