CanvasTest.cpp revision a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2
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, 636 testStep->assertMessage()); 637 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 638 canvas2->getBounder(), testStep->assertMessage()); 639 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 640 canvas2->getTotalMatrix(), testStep->assertMessage()); 641 REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage()); 642 643 // The following test code is commented out because the test fails when 644 // the canvas is an SkPictureRecord or SkDeferredCanvas 645 // Issue: http://code.google.com/p/skia/issues/detail?id=498 646 // Also, creating a LayerIter on an SkProxyCanvas crashes 647 // Issue: http://code.google.com/p/skia/issues/detail?id=499 648 /* 649 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 650 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 651 while (!layerIter1.done() && !layerIter2.done()) { 652 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 653 layerIter2.matrix(), testStep->assertMessage()); 654 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 655 layerIter2.clip(), testStep->assertMessage()); 656 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 657 layerIter2.paint(), testStep->assertMessage()); 658 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 659 layerIter2.x(), testStep->assertMessage()); 660 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 661 layerIter2.y(), testStep->assertMessage()); 662 layerIter1.next(); 663 layerIter2.next(); 664 } 665 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 666 testStep->assertMessage()); 667 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 668 testStep->assertMessage()); 669 */ 670} 671 672// The following class groups static functions that need to access 673// the privates members of SkPictureRecord 674class SkPictureTester { 675private: 676 static int EQ(const SkFlatData* a, const SkFlatData* b) { 677 return *a == *b; 678 } 679 680 static void AssertFlattenedObjectsEqual( 681 SkPictureRecord* referenceRecord, 682 SkPictureRecord* testRecord, 683 skiatest::Reporter* reporter, 684 CanvasTestStep* testStep) { 685 686 REPORTER_ASSERT_MESSAGE(reporter, 687 referenceRecord->fBitmapHeap->count() == 688 testRecord->fBitmapHeap->count(), testStep->assertMessage()); 689 REPORTER_ASSERT_MESSAGE(reporter, 690 referenceRecord->fPaints.count() == 691 testRecord->fPaints.count(), testStep->assertMessage()); 692 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 693 REPORTER_ASSERT_MESSAGE(reporter, 694 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 695 testStep->assertMessage()); 696 } 697 REPORTER_ASSERT_MESSAGE(reporter, 698 !referenceRecord->fPicture->fPathHeap == 699 !testRecord->fPicture->fPathHeap, 700 testStep->assertMessage()); 701 // The following tests are commented out because they currently 702 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 703 /* 704 if (referenceRecord->fPathHeap) { 705 REPORTER_ASSERT_MESSAGE(reporter, 706 referenceRecord->fPathHeap->count() == 707 testRecord->fPathHeap->count(), 708 testStep->assertMessage()); 709 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 710 REPORTER_ASSERT_MESSAGE(reporter, 711 (*referenceRecord->fPathHeap)[i] == 712 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 713 } 714 } 715 */ 716 717 } 718 719public: 720 721 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 722 CanvasTestStep* testStep, 723 uint32_t recordFlags) { 724 // Verify that when a test step is executed twice, no extra resources 725 // are flattened during the second execution 726 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 727 SkPictureRecorder referenceRecorder; 728 SkCanvas* referenceCanvas = referenceRecorder.beginRecording(kWidth, kHeight, 729 NULL, recordFlags); 730 testStep->draw(referenceCanvas, reporter); 731 732 SkPictureRecorder testRecorder; 733 SkCanvas* testCanvas = testRecorder.beginRecording(kWidth, kHeight, 734 NULL, recordFlags); 735 testStep->draw(testCanvas, reporter); 736 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 737 testStep->draw(testCanvas, reporter); 738 739 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(referenceCanvas); 740 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(testCanvas); 741 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 742 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 743 reporter, testStep); 744 } 745}; 746 747static void TestPdfDevice(skiatest::Reporter* reporter, 748 CanvasTestStep* testStep) { 749 SkISize pageSize = SkISize::Make(kWidth, kHeight); 750 SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); 751 SkCanvas canvas(&device); 752 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 753 testStep->draw(&canvas, reporter); 754 SkPDFDocument doc; 755 doc.appendPage(&device); 756 SkDynamicMemoryWStream stream; 757 doc.emitPDF(&stream); 758} 759 760// The following class groups static functions that need to access 761// the privates members of SkDeferredCanvas 762class SkDeferredCanvasTester { 763public: 764 static void TestDeferredCanvasStateConsistency( 765 skiatest::Reporter* reporter, 766 CanvasTestStep* testStep, 767 const SkCanvas& referenceCanvas, bool silent) { 768 769 SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); 770 SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(surface.get())); 771 772 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 773 testStep->draw(deferredCanvas, reporter); 774 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 775 AssertCanvasStatesEqual(reporter, deferredCanvas, &referenceCanvas, 776 testStep); 777 778 if (silent) { 779 deferredCanvas->silentFlush(); 780 } else { 781 deferredCanvas->flush(); 782 } 783 784 testStep->setAssertMessageFormat( 785 silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : 786 kDeferredPostFlushPlaybackAssertMessageFormat); 787 AssertCanvasStatesEqual(reporter, 788 deferredCanvas->immediateCanvas(), 789 &referenceCanvas, testStep); 790 791 // Verified that deferred canvas state is not affected by flushing 792 // pending draw operations 793 794 // The following test code is commented out because it currently fails. 795 // Issue: http://code.google.com/p/skia/issues/detail?id=496 796 /* 797 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 798 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 799 testStep); 800 */ 801 } 802}; 803 804// unused 805static void TestProxyCanvasStateConsistency( 806 skiatest::Reporter* reporter, 807 CanvasTestStep* testStep, 808 const SkCanvas& referenceCanvas) { 809 810 SkBitmap indirectStore; 811 createBitmap(&indirectStore, 0xFFFFFFFF); 812 SkBitmapDevice indirectDevice(indirectStore); 813 SkCanvas indirectCanvas(&indirectDevice); 814 SkProxyCanvas proxyCanvas(&indirectCanvas); 815 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 816 testStep->draw(&proxyCanvas, reporter); 817 // Verify that the SkProxyCanvas reports consitent state 818 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 819 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 820 testStep); 821 // Verify that the indirect canvas reports consitent state 822 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 823 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 824 testStep); 825} 826 827// unused 828static void TestNWayCanvasStateConsistency( 829 skiatest::Reporter* reporter, 830 CanvasTestStep* testStep, 831 const SkCanvas& referenceCanvas) { 832 833 SkBitmap indirectStore1; 834 createBitmap(&indirectStore1, 0xFFFFFFFF); 835 SkBitmapDevice indirectDevice1(indirectStore1); 836 SkCanvas indirectCanvas1(&indirectDevice1); 837 838 SkBitmap indirectStore2; 839 createBitmap(&indirectStore2, 0xFFFFFFFF); 840 SkBitmapDevice indirectDevice2(indirectStore2); 841 SkCanvas indirectCanvas2(&indirectDevice2); 842 843 SkISize canvasSize = referenceCanvas.getDeviceSize(); 844 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 845 nWayCanvas.addCanvas(&indirectCanvas1); 846 nWayCanvas.addCanvas(&indirectCanvas2); 847 848 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 849 testStep->draw(&nWayCanvas, reporter); 850 // Verify that the SkProxyCanvas reports consitent state 851 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 852 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 853 testStep); 854 // Verify that the indirect canvases report consitent state 855 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 856 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 857 testStep); 858 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 859 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 860 testStep); 861} 862 863/* 864 * This sub-test verifies that the test step passes when executed 865 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 866 * that the all canvas derivatives report the same state as an SkCanvas 867 * after having executed the test step. 868 */ 869static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 870 CanvasTestStep* testStep) { 871 SkBitmap referenceStore; 872 createBitmap(&referenceStore, 0xFFFFFFFF); 873 SkBitmapDevice referenceDevice(referenceStore); 874 SkCanvas referenceCanvas(&referenceDevice); 875 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 876 testStep->draw(&referenceCanvas, reporter); 877 878 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); 879 880 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); 881 882 // The following test code is disabled because SkProxyCanvas is 883 // missing a lot of virtual overrides on get* methods, which are used 884 // to verify canvas state. 885 // Issue: http://code.google.com/p/skia/issues/detail?id=500 886 887 if (false) { // avoid bit rot, suppress warning 888 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 889 } 890 891 // The following test code is disabled because SkNWayCanvas does not 892 // report correct clipping and device bounds information 893 // Issue: http://code.google.com/p/skia/issues/detail?id=501 894 895 if (false) { // avoid bit rot, suppress warning 896 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 897 } 898 899 if (false) { // avoid bit rot, suppress warning 900 test_clipVisitor(reporter, &referenceCanvas); 901 } 902} 903 904static void test_newraster(skiatest::Reporter* reporter) { 905 SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 906 SkCanvas* canvas = SkCanvas::NewRaster(info); 907 REPORTER_ASSERT(reporter, canvas); 908 909 SkImageInfo info2; 910 size_t rowBytes; 911 const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); 912 REPORTER_ASSERT(reporter, addr); 913 REPORTER_ASSERT(reporter, info == info2); 914 for (int y = 0; y < info.height(); ++y) { 915 for (int x = 0; x < info.width(); ++x) { 916 REPORTER_ASSERT(reporter, 0 == addr[x]); 917 } 918 addr = (const SkPMColor*)((const char*)addr + rowBytes); 919 } 920 SkDELETE(canvas); 921 922 // now try a deliberately bad info 923 info.fWidth = -1; 924 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 925 926 // too big 927 info.fWidth = 1 << 30; 928 info.fHeight = 1 << 30; 929 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 930 931 // not a valid pixel type 932 info.fWidth = info.fHeight = 10; 933 info.fColorType = kUnknown_SkColorType; 934 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 935 936 // We should succeed with a zero-sized valid info 937 info = SkImageInfo::MakeN32Premul(0, 0); 938 canvas = SkCanvas::NewRaster(info); 939 REPORTER_ASSERT(reporter, canvas); 940 SkDELETE(canvas); 941} 942 943DEF_TEST(Canvas, reporter) { 944 // Init global here because bitmap pixels cannot be alocated during 945 // static initialization 946 kTestBitmap = testBitmap(); 947 948 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 949 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 950 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 951 testStepArray()[testStep], 0); 952 if (testStepArray()[testStep]->enablePdfTesting()) { 953 TestPdfDevice(reporter, testStepArray()[testStep]); 954 } 955 } 956 957 // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) 958 kTestBitmap.reset(); 959 960 test_newraster(reporter); 961} 962