CanvasTest.cpp revision 5c70cdca5efe541b70d010e91607bf8626ea49ca
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_WITH_ASSERT(Translate, 316 translate(SkIntToScalar(1), SkIntToScalar(2))); 317SIMPLE_TEST_STEP_WITH_ASSERT(Scale, 318 scale(SkIntToScalar(1), SkIntToScalar(2))); 319SIMPLE_TEST_STEP_WITH_ASSERT(Rotate, rotate(SkIntToScalar(1))); 320SIMPLE_TEST_STEP_WITH_ASSERT(Skew, 321 skew(SkIntToScalar(1), SkIntToScalar(2))); 322SIMPLE_TEST_STEP_WITH_ASSERT(Concat, concat(kTestMatrix)); 323SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix)); 324SIMPLE_TEST_STEP(ClipRect, clipRect(kTestRect)); 325SIMPLE_TEST_STEP(ClipPath, clipPath(kTestPath)); 326SIMPLE_TEST_STEP(ClipRegion, 327 clipRegion(kTestRegion, SkRegion::kReplace_Op)); 328SIMPLE_TEST_STEP(Clear, clear(kTestColor)); 329SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint)); 330SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode, 331 kTestPointCount, kTestPoints, kTestPaint)); 332SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode, 333 kTestPointCount, kTestPoints, kTestPaint)); 334SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode, 335 kTestPointCount, kTestPoints, kTestPaint)); 336SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint)); 337SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint)); 338SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0)); 339SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint)); 340SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect, 341 NULL)); 342SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap, 343 &kTestIRect, kTestRect, NULL)); 344SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL, 345 kTestRect, &kTestPaint)); 346SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix, 347 NULL)); 348SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap, 349 kTestMatrix, &kTestPaint)); 350SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect, 351 kTestRect, NULL)); 352SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect, 353 kTestRect, &kTestPaint)); 354SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL)); 355SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint)); 356SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(), 357 0, 1, kTestPaint)); 358SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(), 359 kTestText.size(), kTestPoints2, kTestPaint)); 360SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(), 361 kTestText.size(), kTestPath, NULL, kTestPaint)); 362SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(), 363 kTestText.size(), kTestPath, &kTestMatrix, kTestPaint)); 364SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size())); 365SIMPLE_TEST_STEP(BeginGroup, beginCommentGroup(kTestText.c_str())); 366SIMPLE_TEST_STEP(AddComment, addComment(kTestText.c_str(), kTestText.c_str())); 367SIMPLE_TEST_STEP(EndGroup, endCommentGroup()); 368 369/////////////////////////////////////////////////////////////////////////////// 370// Complex test steps 371 372// Save/restore calls cannot be in isolated simple test steps because the test 373// cases that use SkPicture require that save and restore calls be balanced. 374static void SaveMatrixStep(SkCanvas* canvas, 375 skiatest::Reporter* reporter, 376 CanvasTestStep* testStep) { 377 int saveCount = canvas->getSaveCount(); 378 canvas->save(SkCanvas::kMatrix_SaveFlag); 379 canvas->clipRegion(kTestRegion); 380 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 381 canvas->restore(); 382 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 383 testStep->assertMessage()); 384 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 385 testStep->assertMessage()); 386// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() == kTestRegion, testStep->assertMessage()); 387} 388TEST_STEP(SaveMatrix, SaveMatrixStep); 389 390static void SaveClipStep(SkCanvas* canvas, 391 skiatest::Reporter* reporter, 392 CanvasTestStep* testStep) { 393 int saveCount = canvas->getSaveCount(); 394 canvas->save(SkCanvas::kClip_SaveFlag); 395 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 396 canvas->clipRegion(kTestRegion); 397 canvas->restore(); 398 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 399 testStep->assertMessage()); 400 REPORTER_ASSERT_MESSAGE(reporter, !canvas->getTotalMatrix().isIdentity(), 401 testStep->assertMessage()); 402// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); 403} 404TEST_STEP(SaveClip, SaveClipStep); 405 406static void SaveMatrixClipStep(SkCanvas* canvas, 407 skiatest::Reporter* reporter, 408 CanvasTestStep* testStep) { 409 int saveCount = canvas->getSaveCount(); 410 canvas->save(SkCanvas::kMatrixClip_SaveFlag); 411 canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); 412 canvas->clipRegion(kTestRegion); 413 canvas->restore(); 414 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 415 testStep->assertMessage()); 416 REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), 417 testStep->assertMessage()); 418// REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); 419} 420TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); 421 422static void SaveLayerStep(SkCanvas* canvas, 423 skiatest::Reporter* reporter, 424 CanvasTestStep* testStep) { 425 int saveCount = canvas->getSaveCount(); 426 canvas->saveLayer(NULL, NULL); 427 canvas->restore(); 428 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 429 testStep->assertMessage()); 430} 431TEST_STEP(SaveLayer, SaveLayerStep); 432 433static void BoundedSaveLayerStep(SkCanvas* canvas, 434 skiatest::Reporter* reporter, 435 CanvasTestStep* testStep) { 436 int saveCount = canvas->getSaveCount(); 437 canvas->saveLayer(&kTestRect, NULL); 438 canvas->restore(); 439 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 440 testStep->assertMessage()); 441} 442TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); 443 444static void PaintSaveLayerStep(SkCanvas* canvas, 445 skiatest::Reporter* reporter, 446 CanvasTestStep* testStep) { 447 int saveCount = canvas->getSaveCount(); 448 canvas->saveLayer(NULL, &kTestPaint); 449 canvas->restore(); 450 REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, 451 testStep->assertMessage()); 452} 453TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); 454 455static void TwoClipOpsStep(SkCanvas* canvas, 456 skiatest::Reporter*, 457 CanvasTestStep*) { 458 // This test exercises a functionality in SkPicture that leads to the 459 // recording of restore offset placeholders. This test will trigger an 460 // assertion at playback time if the placeholders are not properly 461 // filled when the recording ends. 462 canvas->clipRect(kTestRect); 463 canvas->clipRegion(kTestRegion); 464} 465TEST_STEP(TwoClipOps, TwoClipOpsStep); 466 467// exercise fix for http://code.google.com/p/skia/issues/detail?id=560 468// ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') 469static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, 470 skiatest::Reporter*, 471 CanvasTestStep*) { 472 SkPaint paint; 473 paint.setStrokeWidth(SkIntToScalar(1)); 474 paint.setStyle(SkPaint::kStroke_Style); 475 476 canvas->drawPath(kNearlyZeroLengthPath, paint); 477} 478TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); 479 480static void DrawVerticesShaderTestStep(SkCanvas* canvas, 481 skiatest::Reporter*, 482 CanvasTestStep*) { 483 SkPoint pts[4]; 484 pts[0].set(0, 0); 485 pts[1].set(SkIntToScalar(kWidth), 0); 486 pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); 487 pts[3].set(0, SkIntToScalar(kHeight)); 488 SkPaint paint; 489 SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, 490 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 491 paint.setShader(shader)->unref(); 492 canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, 493 NULL, NULL, NULL, 0, paint); 494} 495// NYI: issue 240. 496TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); 497 498static void DrawPictureTestStep(SkCanvas* canvas, 499 skiatest::Reporter*, 500 CanvasTestStep*) { 501 SkPicture* testPicture = SkNEW_ARGS(SkPicture, ()); 502 SkAutoUnref aup(testPicture); 503 SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight); 504 testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); 505 testCanvas->clipRect(kTestRect); 506 testCanvas->drawRect(kTestRect, kTestPaint); 507 canvas->drawPicture(*testPicture); 508} 509TEST_STEP(DrawPicture, DrawPictureTestStep); 510 511static void SaveRestoreTestStep(SkCanvas* canvas, 512 skiatest::Reporter* reporter, 513 CanvasTestStep* testStep) { 514 int baseSaveCount = canvas->getSaveCount(); 515 int n = canvas->save(); 516 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); 517 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 518 testStep->assertMessage()); 519 canvas->save(); 520 canvas->save(); 521 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), 522 testStep->assertMessage()); 523 canvas->restoreToCount(baseSaveCount + 1); 524 REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), 525 testStep->assertMessage()); 526 527 // should this pin to 1, or be a no-op, or crash? 528 canvas->restoreToCount(0); 529 REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), 530 testStep->assertMessage()); 531} 532TEST_STEP(SaveRestore, SaveRestoreTestStep); 533 534static void DrawLayerTestStep(SkCanvas* canvas, 535 skiatest::Reporter* reporter, 536 CanvasTestStep* testStep) { 537 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 538 testStep->assertMessage()); 539 canvas->save(); 540 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 541 testStep->assertMessage()); 542 canvas->restore(); 543 544 const SkRect* bounds = NULL; // null means include entire bounds 545 const SkPaint* paint = NULL; 546 547 canvas->saveLayer(bounds, paint); 548 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 549 testStep->assertMessage()); 550 canvas->restore(); 551 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 552 testStep->assertMessage()); 553 554 canvas->saveLayer(bounds, paint); 555 canvas->saveLayer(bounds, paint); 556 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 557 testStep->assertMessage()); 558 canvas->restore(); 559 REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), 560 testStep->assertMessage()); 561 canvas->restore(); 562 // now layer count should be 0 563 REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), 564 testStep->assertMessage()); 565} 566TEST_STEP(DrawLayer, DrawLayerTestStep); 567 568static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, 569 skiatest::Reporter*, 570 CanvasTestStep*) { 571 // This test step challenges the TestDeferredCanvasStateConsistency 572 // test cases because the opaque paint can trigger an optimization 573 // that discards previously recorded commands. The challenge is to maintain 574 // correct clip and matrix stack state. 575 canvas->resetMatrix(); 576 canvas->rotate(SkIntToScalar(30)); 577 canvas->save(); 578 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 579 canvas->save(); 580 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 581 SkPaint paint; 582 paint.setColor(0xFFFFFFFF); 583 canvas->drawPaint(paint); 584 canvas->restore(); 585 canvas->restore(); 586} 587TEST_STEP(NestedSaveRestoreWithSolidPaint, \ 588 NestedSaveRestoreWithSolidPaintTestStep); 589 590static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, 591 skiatest::Reporter*, 592 CanvasTestStep*) { 593 // This test step challenges the TestDeferredCanvasStateConsistency 594 // test case because the canvas flush on a deferred canvas will 595 // reset the recording session. The challenge is to maintain correct 596 // clip and matrix stack state on the playback canvas. 597 canvas->resetMatrix(); 598 canvas->rotate(SkIntToScalar(30)); 599 canvas->save(); 600 canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); 601 canvas->save(); 602 canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); 603 canvas->drawRect(kTestRect,kTestPaint); 604 canvas->flush(); 605 canvas->restore(); 606 canvas->restore(); 607} 608TEST_STEP(NestedSaveRestoreWithFlush, \ 609 NestedSaveRestoreWithFlushTestStep); 610 611static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, 612 const SkCanvas* canvas1, 613 const SkCanvas* canvas2, 614 CanvasTestStep* testStep) { 615 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == 616 canvas2->getDeviceSize(), testStep->assertMessage()); 617 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == 618 canvas2->getSaveCount(), testStep->assertMessage()); 619 REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == 620 canvas2->isDrawingToLayer(), testStep->assertMessage()); 621 622 SkRect bounds1, bounds2; 623 REPORTER_ASSERT_MESSAGE(reporter, 624 canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), 625 testStep->assertMessage()); 626 REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, 627 testStep->assertMessage()); 628 629 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == 630 canvas2->getDrawFilter(), testStep->assertMessage()); 631 SkIRect deviceBounds1, deviceBounds2; 632 REPORTER_ASSERT_MESSAGE(reporter, 633 canvas1->getClipDeviceBounds(&deviceBounds1) == 634 canvas2->getClipDeviceBounds(&deviceBounds2), 635 testStep->assertMessage()); 636 REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, 637 testStep->assertMessage()); 638 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() == 639 canvas2->getBounder(), testStep->assertMessage()); 640 REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == 641 canvas2->getTotalMatrix(), testStep->assertMessage()); 642 REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage()); 643 644 // The following test code is commented out because the test fails when 645 // the canvas is an SkPictureRecord or SkDeferredCanvas 646 // Issue: http://code.google.com/p/skia/issues/detail?id=498 647 // Also, creating a LayerIter on an SkProxyCanvas crashes 648 // Issue: http://code.google.com/p/skia/issues/detail?id=499 649 /* 650 SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); 651 SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); 652 while (!layerIter1.done() && !layerIter2.done()) { 653 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == 654 layerIter2.matrix(), testStep->assertMessage()); 655 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == 656 layerIter2.clip(), testStep->assertMessage()); 657 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == 658 layerIter2.paint(), testStep->assertMessage()); 659 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == 660 layerIter2.x(), testStep->assertMessage()); 661 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == 662 layerIter2.y(), testStep->assertMessage()); 663 layerIter1.next(); 664 layerIter2.next(); 665 } 666 REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), 667 testStep->assertMessage()); 668 REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), 669 testStep->assertMessage()); 670 */ 671} 672 673// The following class groups static functions that need to access 674// the privates members of SkPictureRecord 675class SkPictureTester { 676private: 677 static int EQ(const SkFlatData* a, const SkFlatData* b) { 678 return *a == *b; 679 } 680 681 static void AssertFlattenedObjectsEqual( 682 SkPictureRecord* referenceRecord, 683 SkPictureRecord* testRecord, 684 skiatest::Reporter* reporter, 685 CanvasTestStep* testStep) { 686 687 REPORTER_ASSERT_MESSAGE(reporter, 688 referenceRecord->fBitmapHeap->count() == 689 testRecord->fBitmapHeap->count(), testStep->assertMessage()); 690 REPORTER_ASSERT_MESSAGE(reporter, 691 referenceRecord->fPaints.count() == 692 testRecord->fPaints.count(), testStep->assertMessage()); 693 for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { 694 REPORTER_ASSERT_MESSAGE(reporter, 695 EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), 696 testStep->assertMessage()); 697 } 698 REPORTER_ASSERT_MESSAGE(reporter, 699 !referenceRecord->fPathHeap == 700 !testRecord->fPathHeap, 701 testStep->assertMessage()); 702 // The following tests are commented out because they currently 703 // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 704 /* 705 if (referenceRecord->fPathHeap) { 706 REPORTER_ASSERT_MESSAGE(reporter, 707 referenceRecord->fPathHeap->count() == 708 testRecord->fPathHeap->count(), 709 testStep->assertMessage()); 710 for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { 711 REPORTER_ASSERT_MESSAGE(reporter, 712 (*referenceRecord->fPathHeap)[i] == 713 (*testRecord->fPathHeap)[i], testStep->assertMessage()); 714 } 715 } 716 */ 717 718 } 719 720public: 721 722 static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, 723 CanvasTestStep* testStep, 724 uint32_t recordFlags) { 725 // Verify that when a test step is executed twice, no extra resources 726 // are flattened during the second execution 727 testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); 728 SkPicture referencePicture; 729 SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth, 730 kHeight, recordFlags); 731 testStep->draw(referenceCanvas, reporter); 732 SkPicture testPicture; 733 SkCanvas* testCanvas = testPicture.beginRecording(kWidth, 734 kHeight, recordFlags); 735 testStep->draw(testCanvas, reporter); 736 testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); 737 testStep->draw(testCanvas, reporter); 738 739 SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>( 740 referenceCanvas); 741 SkPictureRecord* testRecord = static_cast<SkPictureRecord*>( 742 testCanvas); 743 testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); 744 AssertFlattenedObjectsEqual(referenceRecord, testRecord, 745 reporter, testStep); 746 } 747}; 748 749static void TestPdfDevice(skiatest::Reporter* reporter, 750 CanvasTestStep* testStep) { 751 SkISize pageSize = SkISize::Make(kWidth, kHeight); 752 SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); 753 SkCanvas canvas(&device); 754 testStep->setAssertMessageFormat(kPdfAssertMessageFormat); 755 testStep->draw(&canvas, reporter); 756 SkPDFDocument doc; 757 doc.appendPage(&device); 758 SkDynamicMemoryWStream stream; 759 doc.emitPDF(&stream); 760} 761 762// The following class groups static functions that need to access 763// the privates members of SkDeferredCanvas 764class SkDeferredCanvasTester { 765public: 766 static void TestDeferredCanvasStateConsistency( 767 skiatest::Reporter* reporter, 768 CanvasTestStep* testStep, 769 const SkCanvas& referenceCanvas, bool silent) { 770 771 SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); 772 SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(surface.get())); 773 774 testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); 775 testStep->draw(deferredCanvas, reporter); 776 testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); 777 AssertCanvasStatesEqual(reporter, deferredCanvas, &referenceCanvas, 778 testStep); 779 780 if (silent) { 781 deferredCanvas->silentFlush(); 782 } else { 783 deferredCanvas->flush(); 784 } 785 786 testStep->setAssertMessageFormat( 787 silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : 788 kDeferredPostFlushPlaybackAssertMessageFormat); 789 AssertCanvasStatesEqual(reporter, 790 deferredCanvas->immediateCanvas(), 791 &referenceCanvas, testStep); 792 793 // Verified that deferred canvas state is not affected by flushing 794 // pending draw operations 795 796 // The following test code is commented out because it currently fails. 797 // Issue: http://code.google.com/p/skia/issues/detail?id=496 798 /* 799 testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); 800 AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, 801 testStep); 802 */ 803 } 804}; 805 806// unused 807static void TestProxyCanvasStateConsistency( 808 skiatest::Reporter* reporter, 809 CanvasTestStep* testStep, 810 const SkCanvas& referenceCanvas) { 811 812 SkBitmap indirectStore; 813 createBitmap(&indirectStore, 0xFFFFFFFF); 814 SkBitmapDevice indirectDevice(indirectStore); 815 SkCanvas indirectCanvas(&indirectDevice); 816 SkProxyCanvas proxyCanvas(&indirectCanvas); 817 testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); 818 testStep->draw(&proxyCanvas, reporter); 819 // Verify that the SkProxyCanvas reports consitent state 820 testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); 821 AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, 822 testStep); 823 // Verify that the indirect canvas reports consitent state 824 testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); 825 AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, 826 testStep); 827} 828 829// unused 830static void TestNWayCanvasStateConsistency( 831 skiatest::Reporter* reporter, 832 CanvasTestStep* testStep, 833 const SkCanvas& referenceCanvas) { 834 835 SkBitmap indirectStore1; 836 createBitmap(&indirectStore1, 0xFFFFFFFF); 837 SkBitmapDevice indirectDevice1(indirectStore1); 838 SkCanvas indirectCanvas1(&indirectDevice1); 839 840 SkBitmap indirectStore2; 841 createBitmap(&indirectStore2, 0xFFFFFFFF); 842 SkBitmapDevice indirectDevice2(indirectStore2); 843 SkCanvas indirectCanvas2(&indirectDevice2); 844 845 SkISize canvasSize = referenceCanvas.getDeviceSize(); 846 SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); 847 nWayCanvas.addCanvas(&indirectCanvas1); 848 nWayCanvas.addCanvas(&indirectCanvas2); 849 850 testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); 851 testStep->draw(&nWayCanvas, reporter); 852 // Verify that the SkProxyCanvas reports consitent state 853 testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); 854 AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, 855 testStep); 856 // Verify that the indirect canvases report consitent state 857 testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); 858 AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, 859 testStep); 860 testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); 861 AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, 862 testStep); 863} 864 865/* 866 * This sub-test verifies that the test step passes when executed 867 * with SkCanvas and with classes derrived from SkCanvas. It also verifies 868 * that the all canvas derivatives report the same state as an SkCanvas 869 * after having executed the test step. 870 */ 871static void TestOverrideStateConsistency(skiatest::Reporter* reporter, 872 CanvasTestStep* testStep) { 873 SkBitmap referenceStore; 874 createBitmap(&referenceStore, 0xFFFFFFFF); 875 SkBitmapDevice referenceDevice(referenceStore); 876 SkCanvas referenceCanvas(&referenceDevice); 877 testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); 878 testStep->draw(&referenceCanvas, reporter); 879 880 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); 881 882 SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); 883 884 // The following test code is disabled because SkProxyCanvas is 885 // missing a lot of virtual overrides on get* methods, which are used 886 // to verify canvas state. 887 // Issue: http://code.google.com/p/skia/issues/detail?id=500 888 889 if (false) { // avoid bit rot, suppress warning 890 TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); 891 } 892 893 // The following test code is disabled because SkNWayCanvas does not 894 // report correct clipping and device bounds information 895 // Issue: http://code.google.com/p/skia/issues/detail?id=501 896 897 if (false) { // avoid bit rot, suppress warning 898 TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); 899 } 900 901 if (false) { // avoid bit rot, suppress warning 902 test_clipVisitor(reporter, &referenceCanvas); 903 } 904} 905 906static void test_newraster(skiatest::Reporter* reporter) { 907 SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 908 SkCanvas* canvas = SkCanvas::NewRaster(info); 909 REPORTER_ASSERT(reporter, canvas); 910 911 SkImageInfo info2; 912 size_t rowBytes; 913 const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); 914 REPORTER_ASSERT(reporter, addr); 915 REPORTER_ASSERT(reporter, info == info2); 916 for (int y = 0; y < info.height(); ++y) { 917 for (int x = 0; x < info.width(); ++x) { 918 REPORTER_ASSERT(reporter, 0 == addr[x]); 919 } 920 addr = (const SkPMColor*)((const char*)addr + rowBytes); 921 } 922 SkDELETE(canvas); 923 924 // now try a deliberately bad info 925 info.fWidth = -1; 926 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 927 928 // too big 929 info.fWidth = 1 << 30; 930 info.fHeight = 1 << 30; 931 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 932 933 // not a valid pixel type 934 info.fWidth = info.fHeight = 10; 935 info.fColorType = kUnknown_SkColorType; 936 REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); 937 938 // We should succeed with a zero-sized valid info 939 info = SkImageInfo::MakeN32Premul(0, 0); 940 canvas = SkCanvas::NewRaster(info); 941 REPORTER_ASSERT(reporter, canvas); 942 SkDELETE(canvas); 943} 944 945DEF_TEST(Canvas, reporter) { 946 // Init global here because bitmap pixels cannot be alocated during 947 // static initialization 948 kTestBitmap = testBitmap(); 949 950 for (int testStep = 0; testStep < testStepArray().count(); testStep++) { 951 TestOverrideStateConsistency(reporter, testStepArray()[testStep]); 952 SkPictureTester::TestPictureFlattenedObjectReuse(reporter, 953 testStepArray()[testStep], 0); 954 if (testStepArray()[testStep]->enablePdfTesting()) { 955 TestPdfDevice(reporter, testStepArray()[testStep]); 956 } 957 } 958 959 // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) 960 kTestBitmap.reset(); 961 962 test_newraster(reporter); 963} 964