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