CanvasTest.cpp revision 60bd7519a9db4ddddd95e490f93165e5676f90f5
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 "SkDeferredCanvas.h" 49#include "SkDevice.h" 50#include "SkMatrix.h" 51#include "SkNWayCanvas.h" 52#include "SkPDFDevice.h" 53#include "SkPDFDocument.h" 54#include "SkPaint.h" 55#include "SkPath.h" 56#include "SkPicture.h" 57#include "SkPictureRecord.h" 58#include "SkProxyCanvas.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 bool equal_clips(const SkCanvas& a, const SkCanvas& b) { 68 if (a.isClipEmpty()) { 69 return b.isClipEmpty(); 70 } 71 if (!a.isClipRect()) { 72 // this is liberally true, since we don't expose a way to know this exactly (for non-rects) 73 return !b.isClipRect(); 74 } 75 SkIRect ar, br; 76 a.getClipDeviceBounds(&ar); 77 b.getClipDeviceBounds(&br); 78 return ar == br; 79} 80 81class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor { 82public: 83 Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {} 84 85 virtual void clipRect(const SkRect& r, SkRegion::Op op, bool aa) SK_OVERRIDE { 86 fTarget->clipRect(r, op, aa); 87 } 88 virtual void clipRRect(const SkRRect& r, SkRegion::Op op, bool aa) SK_OVERRIDE { 89 fTarget->clipRRect(r, op, aa); 90 } 91 virtual void clipPath(const SkPath& p, SkRegion::Op op, bool aa) SK_OVERRIDE { 92 fTarget->clipPath(p, op, aa); 93 } 94 95private: 96 SkCanvas* fTarget; 97}; 98 99static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) { 100 SkISize size = canvas->getDeviceSize(); 101 102 SkBitmap bm; 103 bm.setConfig(SkImageInfo::MakeN32Premul(size.width(), size.height())); 104 SkCanvas c(bm); 105 106 Canvas2CanvasClipVisitor visitor(&c); 107 canvas->replayClips(&visitor); 108 109 REPORTER_ASSERT(reporter, equal_clips(c, *canvas)); 110} 111 112static const int kWidth = 2; 113static const int kHeight = 2; 114 115// Format strings that describe the test context. The %s token is where 116// the name of the test step is inserted. The context is required for 117// disambiguating the error in the case of failures that are reported in 118// functions that are called multiple times in different contexts (test 119// cases and test steps). 120static const char* const kDefaultAssertMessageFormat = "%s"; 121static const char* const kCanvasDrawAssertMessageFormat = 122 "Drawing test step %s with SkCanvas"; 123static const char* const kPictureDrawAssertMessageFormat = 124 "Drawing test step %s with SkPicture"; 125static const char* const kPictureSecondDrawAssertMessageFormat = 126 "Duplicate draw of test step %s with SkPicture"; 127static const char* const kDeferredDrawAssertMessageFormat = 128 "Drawing test step %s with SkDeferredCanvas"; 129static const char* const kProxyDrawAssertMessageFormat = 130 "Drawing test step %s with SkProxyCanvas"; 131static const char* const kNWayDrawAssertMessageFormat = 132 "Drawing test step %s with SkNWayCanvas"; 133static const char* const kDeferredPreFlushAssertMessageFormat = 134 "test step %s, SkDeferredCanvas state consistency before flush"; 135static const char* const kDeferredPostFlushPlaybackAssertMessageFormat = 136 "test step %s, SkDeferredCanvas playback canvas state consistency after flush"; 137static const char* const kDeferredPostSilentFlushPlaybackAssertMessageFormat = 138 "test step %s, SkDeferredCanvas playback canvas state consistency after silent flush"; 139static const char* const kPictureResourceReuseMessageFormat = 140 "test step %s, SkPicture duplicate flattened object test"; 141static const char* const kProxyStateAssertMessageFormat = 142 "test step %s, SkProxyCanvas state consistency"; 143static const char* const kProxyIndirectStateAssertMessageFormat = 144 "test step %s, SkProxyCanvas indirect canvas state consistency"; 145static const char* const kNWayStateAssertMessageFormat = 146 "test step %s, SkNWayCanvas state consistency"; 147static const char* const kNWayIndirect1StateAssertMessageFormat = 148 "test step %s, SkNWayCanvas indirect canvas 1 state consistency"; 149static const char* const kNWayIndirect2StateAssertMessageFormat = 150 "test step %s, SkNWayCanvas indirect canvas 2 state consistency"; 151static const char* const kPdfAssertMessageFormat = 152 "PDF sanity check failed %s"; 153 154static void createBitmap(SkBitmap* bm, SkColor color) { 155 bm->allocN32Pixels(kWidth, kHeight); 156 bm->eraseColor(color); 157} 158 159static SkSurface* createSurface(SkColor color) { 160 SkSurface* surface = SkSurface::NewRasterPMColor(kWidth, kHeight); 161 surface->getCanvas()->clear(color); 162 return surface; 163} 164 165class CanvasTestStep; 166static SkTDArray<CanvasTestStep*>& testStepArray() { 167 static SkTDArray<CanvasTestStep*> theTests; 168 return theTests; 169} 170 171class CanvasTestStep { 172public: 173 CanvasTestStep(bool fEnablePdfTesting = true) { 174 *testStepArray().append() = this; 175 fAssertMessageFormat = kDefaultAssertMessageFormat; 176 this->fEnablePdfTesting = fEnablePdfTesting; 177 } 178 virtual ~CanvasTestStep() { } 179 180 virtual void draw(SkCanvas*, skiatest::Reporter*) = 0; 181 virtual const char* name() const = 0; 182 183 const char* assertMessage() { 184 fAssertMessage.printf(fAssertMessageFormat, name()); 185 return fAssertMessage.c_str(); 186 } 187 188 void setAssertMessageFormat(const char* format) { 189 fAssertMessageFormat = format; 190 } 191 192 bool enablePdfTesting() { return fEnablePdfTesting; } 193 194private: 195 SkString fAssertMessage; 196 const char* fAssertMessageFormat; 197 bool fEnablePdfTesting; 198}; 199 200/////////////////////////////////////////////////////////////////////////////// 201// Constants used by test steps 202 203const SkRect kTestRect = 204 SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 205 SkIntToScalar(2), SkIntToScalar(1)); 206static SkMatrix testMatrix() { 207 SkMatrix matrix; 208 matrix.reset(); 209 matrix.setScale(SkIntToScalar(2), SkIntToScalar(3)); 210 return matrix; 211} 212const SkMatrix kTestMatrix = testMatrix(); 213static SkPath test_path() { 214 SkPath path; 215 path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), 216 SkIntToScalar(2), SkIntToScalar(1))); 217 return path; 218} 219const SkPath kTestPath = test_path(); 220static SkPath test_nearly_zero_length_path() { 221 SkPath path; 222 SkPoint pt1 = { 0, 0 }; 223 SkPoint pt2 = { 0, SK_ScalarNearlyZero }; 224 SkPoint pt3 = { SkIntToScalar(1), 0 }; 225 SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; 226 path.moveTo(pt1); 227 path.lineTo(pt2); 228 path.lineTo(pt3); 229 path.lineTo(pt4); 230 return path; 231} 232const SkPath kNearlyZeroLengthPath = test_nearly_zero_length_path(); 233static SkRegion testRegion() { 234 SkRegion region; 235 SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1); 236 region.setRect(rect); 237 return region; 238} 239const SkIRect kTestIRect = SkIRect::MakeXYWH(0, 0, 2, 1); 240const SkRegion kTestRegion = testRegion(); 241const SkColor kTestColor = 0x01020304; 242const SkPaint kTestPaint; 243const SkPoint kTestPoints[3] = { 244 {SkIntToScalar(0), SkIntToScalar(0)}, 245 {SkIntToScalar(2), SkIntToScalar(1)}, 246 {SkIntToScalar(0), SkIntToScalar(2)} 247}; 248const size_t kTestPointCount = 3; 249static SkBitmap testBitmap() { 250 SkBitmap bitmap; 251 createBitmap(&bitmap, 0x05060708); 252 return bitmap; 253} 254SkBitmap kTestBitmap; // cannot be created during static init 255SkString kTestText("Hello World"); 256SkPoint kTestPoints2[] = { 257 { SkIntToScalar(0), SkIntToScalar(1) }, 258 { SkIntToScalar(1), SkIntToScalar(1) }, 259 { SkIntToScalar(2), SkIntToScalar(1) }, 260 { SkIntToScalar(3), SkIntToScalar(1) }, 261 { SkIntToScalar(4), SkIntToScalar(1) }, 262 { SkIntToScalar(5), SkIntToScalar(1) }, 263 { SkIntToScalar(6), SkIntToScalar(1) }, 264 { SkIntToScalar(7), SkIntToScalar(1) }, 265 { SkIntToScalar(8), SkIntToScalar(1) }, 266 { SkIntToScalar(9), SkIntToScalar(1) }, 267 { SkIntToScalar(10), SkIntToScalar(1) }, 268}; 269 270 271/////////////////////////////////////////////////////////////////////////////// 272// Macros for defining test steps 273 274#define TEST_STEP(NAME, FUNCTION) \ 275class NAME##_TestStep : public CanvasTestStep{ \ 276public: \ 277 virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ 278 FUNCTION (canvas, reporter, this); \ 279 } \ 280 virtual const char* name() const {return #NAME ;} \ 281}; \ 282static NAME##_TestStep NAME##_TestStepInstance; 283 284#define TEST_STEP_NO_PDF(NAME, FUNCTION) \ 285class NAME##_TestStep : public CanvasTestStep{ \ 286public: \ 287 NAME##_TestStep() : CanvasTestStep(false) {} \ 288 virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ 289 FUNCTION (canvas, reporter, this); \ 290 } \ 291 virtual const char* name() const {return #NAME ;} \ 292}; \ 293static NAME##_TestStep NAME##_TestStepInstance; 294 295#define SIMPLE_TEST_STEP(NAME, CALL) \ 296static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \ 297 CanvasTestStep*) { \ 298 canvas-> CALL ; \ 299} \ 300TEST_STEP(NAME, NAME##TestStep ) 301 302#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL) \ 303static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \ 304 CanvasTestStep* testStep) { \ 305 REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL , \ 306 testStep->assertMessage()); \ 307} \ 308TEST_STEP(NAME, NAME##TestStep ) 309 310 311/////////////////////////////////////////////////////////////////////////////// 312// Basic test steps for most virtual methods in SkCanvas that draw or affect 313// the state of the canvas. 314 315SIMPLE_TEST_STEP(Translate, translate(SkIntToScalar(1), SkIntToScalar(2))); 316SIMPLE_TEST_STEP(Scale, scale(SkIntToScalar(1), SkIntToScalar(2))); 317SIMPLE_TEST_STEP(Rotate, rotate(SkIntToScalar(1))); 318SIMPLE_TEST_STEP(Skew, skew(SkIntToScalar(1), SkIntToScalar(2))); 319SIMPLE_TEST_STEP(Concat, concat(kTestMatrix)); 320SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix)); 321SIMPLE_TEST_STEP(ClipRect, clipRect(kTestRect)); 322SIMPLE_TEST_STEP(ClipPath, clipPath(kTestPath)); 323SIMPLE_TEST_STEP(ClipRegion, 324 clipRegion(kTestRegion, SkRegion::kReplace_Op)); 325SIMPLE_TEST_STEP(Clear, clear(kTestColor)); 326SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint)); 327SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode, 328 kTestPointCount, kTestPoints, kTestPaint)); 329SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode, 330 kTestPointCount, kTestPoints, kTestPaint)); 331SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode, 332 kTestPointCount, kTestPoints, kTestPaint)); 333SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint)); 334SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint)); 335SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0)); 336SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint)); 337SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect, 338 NULL)); 339SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap, 340 &kTestIRect, kTestRect, NULL)); 341SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL, 342 kTestRect, &kTestPaint)); 343SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix, 344 NULL)); 345SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap, 346 kTestMatrix, &kTestPaint)); 347SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect, 348 kTestRect, NULL)); 349SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect, 350 kTestRect, &kTestPaint)); 351SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL)); 352SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint)); 353SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(), 354 0, 1, kTestPaint)); 355SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(), 356 kTestText.size(), kTestPoints2, kTestPaint)); 357SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(), 358 kTestText.size(), kTestPath, NULL, kTestPaint)); 359SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(), 360 kTestText.size(), kTestPath, &kTestMatrix, kTestPaint)); 361SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size())); 362SIMPLE_TEST_STEP(BeginGroup, beginCommentGroup(kTestText.c_str())); 363SIMPLE_TEST_STEP(AddComment, addComment(kTestText.c_str(), kTestText.c_str())); 364SIMPLE_TEST_STEP(EndGroup, endCommentGroup()); 365 366/////////////////////////////////////////////////////////////////////////////// 367// Complex test steps 368 369// Save/restore calls cannot be in isolated simple test steps because the test 370// cases that use SkPicture require that save and restore calls be balanced. 371static void SaveMatrixStep(SkCanvas* canvas, 372 skiatest::Reporter* reporter, 373 CanvasTestStep* testStep) { 374 int saveCount = canvas->getSaveCount(); 375 canvas->save(SkCanvas::kMatrix_SaveFlag); 376 canvas->clipRegion(kTestRegion); 377 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 378 canvas->restore(); 379 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 380 testStep->assertMessage()); 381 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 382 testStep->assertMessage()); 383// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() == kTestRegion, testStep->assertMessage()); 384} 385TEST_STEP(SaveMatrix, SaveMatrixStep); 386 387static void SaveClipStep(SkCanvas* canvas, 388 skiatest::Reporter* reporter, 389 CanvasTestStep* testStep) { 390 int saveCount = canvas->getSaveCount(); 391 canvas->save(SkCanvas::kClip_SaveFlag); 392 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 393 canvas->clipRegion(kTestRegion); 394 canvas->restore(); 395 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 396 testStep->assertMessage()); 397 REPORTER_ASSERT_MESSAGE(reporter, !canvas->getTotalMatrix().isIdentity(), 398 testStep->assertMessage()); 399// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); 400} 401TEST_STEP(SaveClip, SaveClipStep); 402 403static void SaveMatrixClipStep(SkCanvas* canvas, 404 skiatest::Reporter* reporter, 405 CanvasTestStep* testStep) { 406 int saveCount = canvas->getSaveCount(); 407 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 408 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 409 canvas->clipRegion(kTestRegion); 410 canvas->restore(); 411 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 412 testStep->assertMessage()); 413 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 414 testStep->assertMessage()); 415// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); 416} 417TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 418 419static void SaveLayerStep(SkCanvas* canvas, 420 skiatest::Reporter* reporter, 421 CanvasTestStep* testStep) { 422 int saveCount = canvas->getSaveCount(); 423 canvas->saveLayer(NULL, NULL); 424 canvas->restore(); 425 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 426 testStep->assertMessage()); 427} 428TEST_STEP(SaveLayer, SaveLayerStep); 429 430static void BoundedSaveLayerStep(SkCanvas* canvas, 431 skiatest::Reporter* reporter, 432 CanvasTestStep* testStep) { 433 int saveCount = canvas->getSaveCount(); 434 canvas->saveLayer(&kTestRect, NULL); 435 canvas->restore(); 436 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 437 testStep->assertMessage()); 438} 439TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 440 441static void PaintSaveLayerStep(SkCanvas* canvas, 442 skiatest::Reporter* reporter, 443 CanvasTestStep* testStep) { 444 int saveCount = canvas->getSaveCount(); 445 canvas->saveLayer(NULL, &kTestPaint); 446 canvas->restore(); 447 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 448 testStep->assertMessage()); 449} 450TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 451 452static void TwoClipOpsStep(SkCanvas* canvas, 453 skiatest::Reporter*, 454 CanvasTestStep*) { 455 // This test exercises a functionality in SkPicture that leads to the 456 // recording of restore offset placeholders. This test will trigger an 457 // assertion at playback time if the placeholders are not properly 458 // filled when the recording ends. 459 canvas->clipRect(kTestRect); 460 canvas->clipRegion(kTestRegion); 461} 462TEST_STEP(TwoClipOps, TwoClipOpsStep); 463 464// exercise fix for http://code.google.com/p/skia/issues/detail?id=560 465// ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 466static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, 467 skiatest::Reporter*, 468 CanvasTestStep*) { 469 SkPaint paint; 470 paint.setStrokeWidth(SkIntToScalar(1)); 471 paint.setStyle(SkPaint::kStroke_Style); 472 473 canvas->drawPath(kNearlyZeroLengthPath, paint); 474} 475TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 476 477static void DrawVerticesShaderTestStep(SkCanvas* canvas, 478 skiatest::Reporter*, 479 CanvasTestStep*) { 480 SkPoint pts[4]; 481 pts[0].set(0, 0); 482 pts[1].set(SkIntToScalar(kWidth), 0); 483 pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 484 pts[3].set(0, SkIntToScalar(kHeight)); 485 SkPaint paint; 486 SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, 487 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 488 paint.setShader(shader)->unref(); 489 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 490 NULL, NULL, NULL, 0, paint); 491} 492// NYI: issue 240. 493TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); 494 495static void DrawPictureTestStep(SkCanvas* canvas, 496 skiatest::Reporter*, 497 CanvasTestStep*) { 498 SkPictureRecorder recorder; 499 SkCanvas* testCanvas = recorder.beginRecording(kWidth, kHeight, NULL, 0); 500 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 501 testCanvas->clipRect(kTestRect); 502 testCanvas->drawRect(kTestRect, kTestPaint); 503 SkAutoTUnref<SkPicture> testPicture(recorder.endRecording()); 504 505 canvas->drawPicture(*testPicture); 506} 507TEST_STEP(DrawPicture, DrawPictureTestStep); 508 509static void SaveRestoreTestStep(SkCanvas* canvas, 510 skiatest::Reporter* reporter, 511 CanvasTestStep* testStep) { 512 int baseSaveCount = canvas->getSaveCount(); 513 int n = canvas->save(); 514 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 515 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 516 testStep->assertMessage()); 517 canvas->save(); 518 canvas->save(); 519 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 520 testStep->assertMessage()); 521 canvas->restoreToCount(baseSaveCount + 1); 522 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 523 testStep->assertMessage()); 524 525 // should this pin to 1, or be a no-op, or crash? 526 canvas->restoreToCount(0); 527 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 528 testStep->assertMessage()); 529} 530TEST_STEP(SaveRestore, SaveRestoreTestStep); 531 532static void DrawLayerTestStep(SkCanvas* canvas, 533 skiatest::Reporter* reporter, 534 CanvasTestStep* testStep) { 535 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 536 testStep->assertMessage()); 537 canvas->save(); 538 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 539 testStep->assertMessage()); 540 canvas->restore(); 541 542 const SkRect* bounds = NULL; // null means include entire bounds 543 const SkPaint* paint = NULL; 544 545 canvas->saveLayer(bounds, paint); 546 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 547 testStep->assertMessage()); 548 canvas->restore(); 549 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 550 testStep->assertMessage()); 551 552 canvas->saveLayer(bounds, paint); 553 canvas->saveLayer(bounds, paint); 554 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 555 testStep->assertMessage()); 556 canvas->restore(); 557 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 558 testStep->assertMessage()); 559 canvas->restore(); 560 // now layer count should be 0 561 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 562 testStep->assertMessage()); 563} 564TEST_STEP(DrawLayer, DrawLayerTestStep); 565 566static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, 567 skiatest::Reporter*, 568 CanvasTestStep*) { 569 // This test step challenges the TestDeferredCanvasStateConsistency 570 // test cases because the opaque paint can trigger an optimization 571 // that discards previously recorded commands. The challenge is to maintain 572 // correct clip and matrix stack state. 573 canvas->resetMatrix(); 574 canvas->rotate(SkIntToScalar(30)); 575 canvas->save(); 576 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 577 canvas->save(); 578 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 579 SkPaint paint; 580 paint.setColor(0xFFFFFFFF); 581 canvas->drawPaint(paint); 582 canvas->restore(); 583 canvas->restore(); 584} 585TEST_STEP(NestedSaveRestoreWithSolidPaint, \ 586 NestedSaveRestoreWithSolidPaintTestStep); 587 588static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, 589 skiatest::Reporter*, 590 CanvasTestStep*) { 591 // This test step challenges the TestDeferredCanvasStateConsistency 592 // test case because the canvas flush on a deferred canvas will 593 // reset the recording session. The challenge is to maintain correct 594 // clip and matrix stack state on the playback canvas. 595 canvas->resetMatrix(); 596 canvas->rotate(SkIntToScalar(30)); 597 canvas->save(); 598 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 599 canvas->save(); 600 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 601 canvas->drawRect(kTestRect,kTestPaint); 602 canvas->flush(); 603 canvas->restore(); 604 canvas->restore(); 605} 606TEST_STEP(NestedSaveRestoreWithFlush, \ 607 NestedSaveRestoreWithFlushTestStep); 608 609static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, 610 const SkCanvas* canvas1, 611 const SkCanvas* canvas2, 612 CanvasTestStep* testStep) { 613 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 614 canvas2->getDeviceSize(), testStep->assertMessage()); 615 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 616 canvas2->getSaveCount(), testStep->assertMessage()); 617 REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == 618 canvas2->isDrawingToLayer(), testStep->assertMessage()); 619 620 SkRect bounds1, bounds2; 621 REPORTER_ASSERT_MESSAGE(reporter, 622 canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), 623 testStep->assertMessage()); 624 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 625 testStep->assertMessage()); 626 627 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 628 canvas2->getDrawFilter(), testStep->assertMessage()); 629 SkIRect deviceBounds1, deviceBounds2; 630 REPORTER_ASSERT_MESSAGE(reporter, 631 canvas1->getClipDeviceBounds(&deviceBounds1) == 632 canvas2->getClipDeviceBounds(&deviceBounds2), 633 testStep->assertMessage()); 634 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, 635 testStep->assertMessage()); 636 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 637 canvas2->getBounder(), testStep->assertMessage()); 638 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 639 canvas2->getTotalMatrix(), testStep->assertMessage()); 640 REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage()); 641 642 // The following test code is commented out because the test fails when 643 // the canvas is an SkPictureRecord or SkDeferredCanvas 644 // Issue: http://code.google.com/p/skia/issues/detail?id=498 645 // Also, creating a LayerIter on an SkProxyCanvas crashes 646 // Issue: http://code.google.com/p/skia/issues/detail?id=499 647 /* 648 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 649 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 650 while (!layerIter1.done() && !layerIter2.done()) { 651 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 652 layerIter2.matrix(), testStep->assertMessage()); 653 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 654 layerIter2.clip(), testStep->assertMessage()); 655 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 656 layerIter2.paint(), testStep->assertMessage()); 657 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 658 layerIter2.x(), testStep->assertMessage()); 659 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 660 layerIter2.y(), testStep->assertMessage()); 661 layerIter1.next(); 662 layerIter2.next(); 663 } 664 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 665 testStep->assertMessage()); 666 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 667 testStep->assertMessage()); 668 */ 669} 670 671// The following class groups static functions that need to access 672// the privates members of SkPictureRecord 673class SkPictureTester { 674private: 675 static int EQ(const SkFlatData* a, const SkFlatData* b) { 676 return *a == *b; 677 } 678 679 static void AssertFlattenedObjectsEqual( 680 SkPictureRecord* referenceRecord, 681 SkPictureRecord* testRecord, 682 skiatest::Reporter* reporter, 683 CanvasTestStep* testStep) { 684 685 REPORTER_ASSERT_MESSAGE(reporter, 686 referenceRecord->fBitmapHeap->count() == 687 testRecord->fBitmapHeap->count(), testStep->assertMessage()); 688 REPORTER_ASSERT_MESSAGE(reporter, 689 referenceRecord->fPaints.count() == 690 testRecord->fPaints.count(), testStep->assertMessage()); 691 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 692 REPORTER_ASSERT_MESSAGE(reporter, 693 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 694 testStep->assertMessage()); 695 } 696 REPORTER_ASSERT_MESSAGE(reporter, 697 !referenceRecord->fPathHeap == 698 !testRecord->fPathHeap, 699 testStep->assertMessage()); 700 // The following tests are commented out because they currently 701 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 702 /* 703 if (referenceRecord->fPathHeap) { 704 REPORTER_ASSERT_MESSAGE(reporter, 705 referenceRecord->fPathHeap->count() == 706 testRecord->fPathHeap->count(), 707 testStep->assertMessage()); 708 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 709 REPORTER_ASSERT_MESSAGE(reporter, 710 (*referenceRecord->fPathHeap)[i] == 711 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 712 } 713 } 714 */ 715 716 } 717 718public: 719 720 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 721 CanvasTestStep* testStep, 722 uint32_t recordFlags) { 723 // Verify that when a test step is executed twice, no extra resources 724 // are flattened during the second execution 725 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 726 SkPictureRecorder referenceRecorder; 727 SkCanvas* referenceCanvas = referenceRecorder.beginRecording(kWidth, kHeight, 728 NULL, recordFlags); 729 testStep->draw(referenceCanvas, reporter); 730 731 SkPictureRecorder testRecorder; 732 SkCanvas* testCanvas = testRecorder.beginRecording(kWidth, kHeight, 733 NULL, recordFlags); 734 testStep->draw(testCanvas, reporter); 735 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 736 testStep->draw(testCanvas, reporter); 737 738 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(referenceCanvas); 739 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(testCanvas); 740 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 741 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 742 reporter, testStep); 743 } 744}; 745 746static void TestPdfDevice(skiatest::Reporter* reporter, 747 CanvasTestStep* testStep) { 748 SkISize pageSize = SkISize::Make(kWidth, kHeight); 749 SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); 750 SkCanvas canvas(&device); 751 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 752 testStep->draw(&canvas, reporter); 753 SkPDFDocument doc; 754 doc.appendPage(&device); 755 SkDynamicMemoryWStream stream; 756 doc.emitPDF(&stream); 757} 758 759// The following class groups static functions that need to access 760// the privates members of SkDeferredCanvas 761class SkDeferredCanvasTester { 762public: 763 static void TestDeferredCanvasStateConsistency( 764 skiatest::Reporter* reporter, 765 CanvasTestStep* testStep, 766 const SkCanvas& referenceCanvas, bool silent) { 767 768 SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); 769 SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(surface.get())); 770 771 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 772 testStep->draw(deferredCanvas, reporter); 773 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 774 AssertCanvasStatesEqual(reporter, deferredCanvas, &referenceCanvas, 775 testStep); 776 777 if (silent) { 778 deferredCanvas->silentFlush(); 779 } else { 780 deferredCanvas->flush(); 781 } 782 783 testStep->setAssertMessageFormat( 784 silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : 785 kDeferredPostFlushPlaybackAssertMessageFormat); 786 AssertCanvasStatesEqual(reporter, 787 deferredCanvas->immediateCanvas(), 788 &referenceCanvas, testStep); 789 790 // Verified that deferred canvas state is not affected by flushing 791 // pending draw operations 792 793 // The following test code is commented out because it currently fails. 794 // Issue: http://code.google.com/p/skia/issues/detail?id=496 795 /* 796 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 797 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 798 testStep); 799 */ 800 } 801}; 802 803// unused 804static void TestProxyCanvasStateConsistency( 805 skiatest::Reporter* reporter, 806 CanvasTestStep* testStep, 807 const SkCanvas& referenceCanvas) { 808 809 SkBitmap indirectStore; 810 createBitmap(&indirectStore, 0xFFFFFFFF); 811 SkBitmapDevice indirectDevice(indirectStore); 812 SkCanvas indirectCanvas(&indirectDevice); 813 SkProxyCanvas proxyCanvas(&indirectCanvas); 814 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 815 testStep->draw(&proxyCanvas, reporter); 816 // Verify that the SkProxyCanvas reports consitent state 817 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 818 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 819 testStep); 820 // Verify that the indirect canvas reports consitent state 821 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 822 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 823 testStep); 824} 825 826// unused 827static void TestNWayCanvasStateConsistency( 828 skiatest::Reporter* reporter, 829 CanvasTestStep* testStep, 830 const SkCanvas& referenceCanvas) { 831 832 SkBitmap indirectStore1; 833 createBitmap(&indirectStore1, 0xFFFFFFFF); 834 SkBitmapDevice indirectDevice1(indirectStore1); 835 SkCanvas indirectCanvas1(&indirectDevice1); 836 837 SkBitmap indirectStore2; 838 createBitmap(&indirectStore2, 0xFFFFFFFF); 839 SkBitmapDevice indirectDevice2(indirectStore2); 840 SkCanvas indirectCanvas2(&indirectDevice2); 841 842 SkISize canvasSize = referenceCanvas.getDeviceSize(); 843 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 844 nWayCanvas.addCanvas(&indirectCanvas1); 845 nWayCanvas.addCanvas(&indirectCanvas2); 846 847 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 848 testStep->draw(&nWayCanvas, reporter); 849 // Verify that the SkProxyCanvas reports consitent state 850 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 851 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 852 testStep); 853 // Verify that the indirect canvases report consitent state 854 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 855 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 856 testStep); 857 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 858 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 859 testStep); 860} 861 862/* 863 * This sub-test verifies that the test step passes when executed 864 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 865 * that the all canvas derivatives report the same state as an SkCanvas 866 * after having executed the test step. 867 */ 868static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 869 CanvasTestStep* testStep) { 870 SkBitmap referenceStore; 871 createBitmap(&referenceStore, 0xFFFFFFFF); 872 SkBitmapDevice referenceDevice(referenceStore); 873 SkCanvas referenceCanvas(&referenceDevice); 874 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 875 testStep->draw(&referenceCanvas, reporter); 876 877 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); 878 879 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); 880 881 // The following test code is disabled because SkProxyCanvas is 882 // missing a lot of virtual overrides on get* methods, which are used 883 // to verify canvas state. 884 // Issue: http://code.google.com/p/skia/issues/detail?id=500 885 886 if (false) { // avoid bit rot, suppress warning 887 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 888 } 889 890 // The following test code is disabled because SkNWayCanvas does not 891 // report correct clipping and device bounds information 892 // Issue: http://code.google.com/p/skia/issues/detail?id=501 893 894 if (false) { // avoid bit rot, suppress warning 895 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 896 } 897 898 if (false) { // avoid bit rot, suppress warning 899 test_clipVisitor(reporter, &referenceCanvas); 900 } 901} 902 903static void test_newraster(skiatest::Reporter* reporter) { 904 SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 905 SkCanvas* canvas = SkCanvas::NewRaster(info); 906 REPORTER_ASSERT(reporter, canvas); 907 908 SkImageInfo info2; 909 size_t rowBytes; 910 const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); 911 REPORTER_ASSERT(reporter, addr); 912 REPORTER_ASSERT(reporter, info == info2); 913 for (int y = 0; y < info.height(); ++y) { 914 for (int x = 0; x < info.width(); ++x) { 915 REPORTER_ASSERT(reporter, 0 == addr[x]); 916 } 917 addr = (const SkPMColor*)((const char*)addr + rowBytes); 918 } 919 SkDELETE(canvas); 920 921 // now try a deliberately bad info 922 info.fWidth = -1; 923 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 924 925 // too big 926 info.fWidth = 1 << 30; 927 info.fHeight = 1 << 30; 928 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 929 930 // not a valid pixel type 931 info.fWidth = info.fHeight = 10; 932 info.fColorType = kUnknown_SkColorType; 933 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 934 935 // We should succeed with a zero-sized valid info 936 info = SkImageInfo::MakeN32Premul(0, 0); 937 canvas = SkCanvas::NewRaster(info); 938 REPORTER_ASSERT(reporter, canvas); 939 SkDELETE(canvas); 940} 941 942DEF_TEST(Canvas, reporter) { 943 // Init global here because bitmap pixels cannot be alocated during 944 // static initialization 945 kTestBitmap = testBitmap(); 946 947 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 948 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 949 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 950 testStepArray()[testStep], 0); 951 if (testStepArray()[testStep]->enablePdfTesting()) { 952 TestPdfDevice(reporter, testStepArray()[testStep]); 953 } 954 } 955 956 // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) 957 kTestBitmap.reset(); 958 959 test_newraster(reporter); 960} 961