|  | /* | 
|  | * Copyright 2012 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | /*  Description: | 
|  | *      This test defines a series of elementatry test steps that perform | 
|  | *      a single or a small group of canvas API calls. Each test step is | 
|  | *      used in several test cases that verify that different types of SkCanvas | 
|  | *      flavors and derivatives pass it and yield consistent behavior. The | 
|  | *      test cases analyse results that are queryable through the API. They do | 
|  | *      not look at rendering results. | 
|  | * | 
|  | *  Adding test stepss: | 
|  | *      The general pattern for creating a new test step is to write a test | 
|  | *      function of the form: | 
|  | * | 
|  | *          static void MyTestStepFunction(SkCanvas* canvas, | 
|  | *                                         skiatest::Reporter* reporter, | 
|  | *                                         CanvasTestStep* testStep) | 
|  | *          { | 
|  | *              canvas->someCanvasAPImethod(); | 
|  | *              (...) | 
|  | *              REPORTER_ASSERT_MESSAGE(reporter, (...), \ | 
|  | *                  testStep->assertMessage()); | 
|  | *          } | 
|  | * | 
|  | *      The definition of the test step function should be followed by an | 
|  | *      invocation of the TEST_STEP macro, which generates a class and | 
|  | *      instance for the test step: | 
|  | * | 
|  | *          TEST_STEP(MyTestStep, MyTestStepFunction) | 
|  | * | 
|  | *      There are also short hand macros for defining simple test steps | 
|  | *      in a single line of code.  A simple test step is a one that is made | 
|  | *      of a single canvas API call. | 
|  | * | 
|  | *          SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod()); | 
|  | * | 
|  | *      There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that | 
|  | *      works the same way as SIMPLE_TEST_STEP, and additionally verifies | 
|  | *      that the invoked method returns a non-zero value. | 
|  | */ | 
|  | #include "SkBitmap.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "SkDeferredCanvas.h" | 
|  | #include "SkDevice.h" | 
|  | #include "SkMatrix.h" | 
|  | #include "SkNWayCanvas.h" | 
|  | #include "SkPDFDevice.h" | 
|  | #include "SkPDFDocument.h" | 
|  | #include "SkPaint.h" | 
|  | #include "SkPath.h" | 
|  | #include "SkPicture.h" | 
|  | #include "SkPictureRecord.h" | 
|  | #include "SkPictureRecorder.h" | 
|  | #include "SkProxyCanvas.h" | 
|  | #include "SkRect.h" | 
|  | #include "SkRegion.h" | 
|  | #include "SkShader.h" | 
|  | #include "SkStream.h" | 
|  | #include "SkSurface.h" | 
|  | #include "SkTDArray.h" | 
|  | #include "Test.h" | 
|  |  | 
|  | static bool equal_clips(const SkCanvas& a, const SkCanvas& b) { | 
|  | if (a.isClipEmpty()) { | 
|  | return b.isClipEmpty(); | 
|  | } | 
|  | if (!a.isClipRect()) { | 
|  | // this is liberally true, since we don't expose a way to know this exactly (for non-rects) | 
|  | return !b.isClipRect(); | 
|  | } | 
|  | SkIRect ar, br; | 
|  | a.getClipDeviceBounds(&ar); | 
|  | b.getClipDeviceBounds(&br); | 
|  | return ar == br; | 
|  | } | 
|  |  | 
|  | class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor { | 
|  | public: | 
|  | Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {} | 
|  |  | 
|  | virtual void clipRect(const SkRect& r, SkRegion::Op op, bool aa) SK_OVERRIDE { | 
|  | fTarget->clipRect(r, op, aa); | 
|  | } | 
|  | virtual void clipRRect(const SkRRect& r, SkRegion::Op op, bool aa) SK_OVERRIDE { | 
|  | fTarget->clipRRect(r, op, aa); | 
|  | } | 
|  | virtual void clipPath(const SkPath& p, SkRegion::Op op, bool aa) SK_OVERRIDE { | 
|  | fTarget->clipPath(p, op, aa); | 
|  | } | 
|  |  | 
|  | private: | 
|  | SkCanvas* fTarget; | 
|  | }; | 
|  |  | 
|  | static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) { | 
|  | SkISize size = canvas->getDeviceSize(); | 
|  |  | 
|  | SkBitmap bm; | 
|  | bm.setInfo(SkImageInfo::MakeN32Premul(size.width(), size.height())); | 
|  | SkCanvas c(bm); | 
|  |  | 
|  | Canvas2CanvasClipVisitor visitor(&c); | 
|  | canvas->replayClips(&visitor); | 
|  |  | 
|  | REPORTER_ASSERT(reporter, equal_clips(c, *canvas)); | 
|  | } | 
|  |  | 
|  | static const int kWidth = 2; | 
|  | static const int kHeight = 2; | 
|  |  | 
|  | // Format strings that describe the test context.  The %s token is where | 
|  | // the name of the test step is inserted.  The context is required for | 
|  | // disambiguating the error in the case of failures that are reported in | 
|  | // functions that are called multiple times in different contexts (test | 
|  | // cases and test steps). | 
|  | static const char* const kDefaultAssertMessageFormat = "%s"; | 
|  | static const char* const kCanvasDrawAssertMessageFormat = | 
|  | "Drawing test step %s with SkCanvas"; | 
|  | static const char* const kPictureDrawAssertMessageFormat = | 
|  | "Drawing test step %s with SkPicture"; | 
|  | static const char* const kPictureSecondDrawAssertMessageFormat = | 
|  | "Duplicate draw of test step %s with SkPicture"; | 
|  | static const char* const kDeferredDrawAssertMessageFormat = | 
|  | "Drawing test step %s with SkDeferredCanvas"; | 
|  | static const char* const kProxyDrawAssertMessageFormat = | 
|  | "Drawing test step %s with SkProxyCanvas"; | 
|  | static const char* const kNWayDrawAssertMessageFormat = | 
|  | "Drawing test step %s with SkNWayCanvas"; | 
|  | static const char* const kDeferredPreFlushAssertMessageFormat = | 
|  | "test step %s, SkDeferredCanvas state consistency before flush"; | 
|  | static const char* const kDeferredPostFlushPlaybackAssertMessageFormat = | 
|  | "test step %s, SkDeferredCanvas playback canvas state consistency after flush"; | 
|  | static const char* const kDeferredPostSilentFlushPlaybackAssertMessageFormat = | 
|  | "test step %s, SkDeferredCanvas playback canvas state consistency after silent flush"; | 
|  | static const char* const kPictureResourceReuseMessageFormat = | 
|  | "test step %s, SkPicture duplicate flattened object test"; | 
|  | static const char* const kProxyStateAssertMessageFormat = | 
|  | "test step %s, SkProxyCanvas state consistency"; | 
|  | static const char* const kProxyIndirectStateAssertMessageFormat = | 
|  | "test step %s, SkProxyCanvas indirect canvas state consistency"; | 
|  | static const char* const kNWayStateAssertMessageFormat = | 
|  | "test step %s, SkNWayCanvas state consistency"; | 
|  | static const char* const kNWayIndirect1StateAssertMessageFormat = | 
|  | "test step %s, SkNWayCanvas indirect canvas 1 state consistency"; | 
|  | static const char* const kNWayIndirect2StateAssertMessageFormat = | 
|  | "test step %s, SkNWayCanvas indirect canvas 2 state consistency"; | 
|  | static const char* const kPdfAssertMessageFormat = | 
|  | "PDF sanity check failed %s"; | 
|  |  | 
|  | static void createBitmap(SkBitmap* bm, SkColor color) { | 
|  | bm->allocN32Pixels(kWidth, kHeight); | 
|  | bm->eraseColor(color); | 
|  | } | 
|  |  | 
|  | static SkSurface* createSurface(SkColor color) { | 
|  | SkSurface* surface = SkSurface::NewRasterPMColor(kWidth, kHeight); | 
|  | surface->getCanvas()->clear(color); | 
|  | return surface; | 
|  | } | 
|  |  | 
|  | class CanvasTestStep; | 
|  | static SkTDArray<CanvasTestStep*>& testStepArray() { | 
|  | static SkTDArray<CanvasTestStep*> theTests; | 
|  | return theTests; | 
|  | } | 
|  |  | 
|  | class CanvasTestStep { | 
|  | public: | 
|  | CanvasTestStep(bool fEnablePdfTesting = true) { | 
|  | *testStepArray().append() = this; | 
|  | fAssertMessageFormat = kDefaultAssertMessageFormat; | 
|  | this->fEnablePdfTesting = fEnablePdfTesting; | 
|  | } | 
|  | virtual ~CanvasTestStep() { } | 
|  |  | 
|  | virtual void draw(SkCanvas*, skiatest::Reporter*) = 0; | 
|  | virtual const char* name() const = 0; | 
|  |  | 
|  | const char* assertMessage() { | 
|  | fAssertMessage.printf(fAssertMessageFormat, name()); | 
|  | return fAssertMessage.c_str(); | 
|  | } | 
|  |  | 
|  | void setAssertMessageFormat(const char* format) { | 
|  | fAssertMessageFormat = format; | 
|  | } | 
|  |  | 
|  | bool enablePdfTesting() { return fEnablePdfTesting; } | 
|  |  | 
|  | private: | 
|  | SkString fAssertMessage; | 
|  | const char* fAssertMessageFormat; | 
|  | bool fEnablePdfTesting; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Constants used by test steps | 
|  |  | 
|  | const SkRect kTestRect = | 
|  | SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), | 
|  | SkIntToScalar(2), SkIntToScalar(1)); | 
|  | static SkMatrix testMatrix() { | 
|  | SkMatrix matrix; | 
|  | matrix.reset(); | 
|  | matrix.setScale(SkIntToScalar(2), SkIntToScalar(3)); | 
|  | return matrix; | 
|  | } | 
|  | const SkMatrix kTestMatrix = testMatrix(); | 
|  | static SkPath test_path() { | 
|  | SkPath path; | 
|  | path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0), | 
|  | SkIntToScalar(2), SkIntToScalar(1))); | 
|  | return path; | 
|  | } | 
|  | const SkPath kTestPath = test_path(); | 
|  | static SkPath test_nearly_zero_length_path() { | 
|  | SkPath path; | 
|  | SkPoint pt1 = { 0, 0 }; | 
|  | SkPoint pt2 = { 0, SK_ScalarNearlyZero }; | 
|  | SkPoint pt3 = { SkIntToScalar(1), 0 }; | 
|  | SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 }; | 
|  | path.moveTo(pt1); | 
|  | path.lineTo(pt2); | 
|  | path.lineTo(pt3); | 
|  | path.lineTo(pt4); | 
|  | return path; | 
|  | } | 
|  | const SkPath kNearlyZeroLengthPath = test_nearly_zero_length_path(); | 
|  | static SkRegion testRegion() { | 
|  | SkRegion region; | 
|  | SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1); | 
|  | region.setRect(rect); | 
|  | return region; | 
|  | } | 
|  | const SkIRect kTestIRect = SkIRect::MakeXYWH(0, 0, 2, 1); | 
|  | const SkRegion kTestRegion = testRegion(); | 
|  | const SkColor kTestColor = 0x01020304; | 
|  | const SkPaint kTestPaint; | 
|  | const SkPoint kTestPoints[3] = { | 
|  | {SkIntToScalar(0), SkIntToScalar(0)}, | 
|  | {SkIntToScalar(2), SkIntToScalar(1)}, | 
|  | {SkIntToScalar(0), SkIntToScalar(2)} | 
|  | }; | 
|  | const size_t kTestPointCount = 3; | 
|  | static SkBitmap testBitmap() { | 
|  | SkBitmap bitmap; | 
|  | createBitmap(&bitmap, 0x05060708); | 
|  | return bitmap; | 
|  | } | 
|  | SkBitmap kTestBitmap; // cannot be created during static init | 
|  | SkString kTestText("Hello World"); | 
|  | SkPoint kTestPoints2[] = { | 
|  | { SkIntToScalar(0), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(1), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(2), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(3), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(4), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(5), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(6), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(7), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(8), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(9), SkIntToScalar(1) }, | 
|  | { SkIntToScalar(10), SkIntToScalar(1) }, | 
|  | }; | 
|  |  | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Macros for defining test steps | 
|  |  | 
|  | #define TEST_STEP(NAME, FUNCTION)                                       \ | 
|  | class NAME##_TestStep : public CanvasTestStep{                          \ | 
|  | public:                                                                 \ | 
|  | virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ | 
|  | FUNCTION (canvas, reporter, this);                              \ | 
|  | }                                                                   \ | 
|  | virtual const char* name() const {return #NAME ;}                   \ | 
|  | };                                                                      \ | 
|  | static NAME##_TestStep NAME##_TestStepInstance; | 
|  |  | 
|  | #define TEST_STEP_NO_PDF(NAME, FUNCTION)                                       \ | 
|  | class NAME##_TestStep : public CanvasTestStep{                          \ | 
|  | public:                                                                 \ | 
|  | NAME##_TestStep() : CanvasTestStep(false) {}                        \ | 
|  | virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \ | 
|  | FUNCTION (canvas, reporter, this);                              \ | 
|  | }                                                                   \ | 
|  | virtual const char* name() const {return #NAME ;}                   \ | 
|  | };                                                                      \ | 
|  | static NAME##_TestStep NAME##_TestStepInstance; | 
|  |  | 
|  | #define SIMPLE_TEST_STEP(NAME, CALL)                              \ | 
|  | static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \ | 
|  | CanvasTestStep*) {                                            \ | 
|  | canvas-> CALL ;                                               \ | 
|  | }                                                                 \ | 
|  | TEST_STEP(NAME, NAME##TestStep ) | 
|  |  | 
|  | #define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL)                           \ | 
|  | static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \ | 
|  | CanvasTestStep* testStep) {                                            \ | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL ,                      \ | 
|  | testStep->assertMessage());                                        \ | 
|  | }                                                                          \ | 
|  | TEST_STEP(NAME, NAME##TestStep ) | 
|  |  | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Basic test steps for most virtual methods in SkCanvas that draw or affect | 
|  | // the state of the canvas. | 
|  |  | 
|  | SIMPLE_TEST_STEP(Translate, translate(SkIntToScalar(1), SkIntToScalar(2))); | 
|  | SIMPLE_TEST_STEP(Scale, scale(SkIntToScalar(1), SkIntToScalar(2))); | 
|  | SIMPLE_TEST_STEP(Rotate, rotate(SkIntToScalar(1))); | 
|  | SIMPLE_TEST_STEP(Skew, skew(SkIntToScalar(1), SkIntToScalar(2))); | 
|  | SIMPLE_TEST_STEP(Concat, concat(kTestMatrix)); | 
|  | SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix)); | 
|  | SIMPLE_TEST_STEP(ClipRect, clipRect(kTestRect)); | 
|  | SIMPLE_TEST_STEP(ClipPath, clipPath(kTestPath)); | 
|  | SIMPLE_TEST_STEP(ClipRegion, | 
|  | clipRegion(kTestRegion, SkRegion::kReplace_Op)); | 
|  | SIMPLE_TEST_STEP(Clear, clear(kTestColor)); | 
|  | SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode, | 
|  | kTestPointCount, kTestPoints, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode, | 
|  | kTestPointCount, kTestPoints, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode, | 
|  | kTestPointCount, kTestPoints, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect, | 
|  | NULL)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap, | 
|  | &kTestIRect, kTestRect, NULL)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL, | 
|  | kTestRect, &kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix, | 
|  | NULL)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap, | 
|  | kTestMatrix, &kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect, | 
|  | kTestRect, NULL)); | 
|  | SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect, | 
|  | kTestRect, &kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL)); | 
|  | SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(), | 
|  | 0, 1, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(), | 
|  | kTestText.size(), kTestPoints2, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(), | 
|  | kTestText.size(), kTestPath, NULL, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(), | 
|  | kTestText.size(), kTestPath, &kTestMatrix, kTestPaint)); | 
|  | SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size())); | 
|  | SIMPLE_TEST_STEP(BeginGroup, beginCommentGroup(kTestText.c_str())); | 
|  | SIMPLE_TEST_STEP(AddComment, addComment(kTestText.c_str(), kTestText.c_str())); | 
|  | SIMPLE_TEST_STEP(EndGroup, endCommentGroup()); | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  | // Complex test steps | 
|  |  | 
|  | static void SaveMatrixClipStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | int saveCount = canvas->getSaveCount(); | 
|  | canvas->save(); | 
|  | canvas->translate(SkIntToScalar(1), SkIntToScalar(2)); | 
|  | canvas->clipRegion(kTestRegion); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, | 
|  | testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(), | 
|  | testStep->assertMessage()); | 
|  | //    REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(SaveMatrixClip, SaveMatrixClipStep); | 
|  |  | 
|  | static void SaveLayerStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | int saveCount = canvas->getSaveCount(); | 
|  | canvas->saveLayer(NULL, NULL); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(SaveLayer, SaveLayerStep); | 
|  |  | 
|  | static void BoundedSaveLayerStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | int saveCount = canvas->getSaveCount(); | 
|  | canvas->saveLayer(&kTestRect, NULL); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep); | 
|  |  | 
|  | static void PaintSaveLayerStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | int saveCount = canvas->getSaveCount(); | 
|  | canvas->saveLayer(NULL, &kTestPaint); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount, | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(PaintSaveLayer, PaintSaveLayerStep); | 
|  |  | 
|  | static void TwoClipOpsStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | // This test exercises a functionality in SkPicture that leads to the | 
|  | // recording of restore offset placeholders.  This test will trigger an | 
|  | // assertion at playback time if the placeholders are not properly | 
|  | // filled when the recording ends. | 
|  | canvas->clipRect(kTestRect); | 
|  | canvas->clipRegion(kTestRegion); | 
|  | } | 
|  | TEST_STEP(TwoClipOps, TwoClipOpsStep); | 
|  |  | 
|  | // exercise fix for http://code.google.com/p/skia/issues/detail?id=560 | 
|  | // ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero') | 
|  | static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | SkPaint paint; | 
|  | paint.setStrokeWidth(SkIntToScalar(1)); | 
|  | paint.setStyle(SkPaint::kStroke_Style); | 
|  |  | 
|  | canvas->drawPath(kNearlyZeroLengthPath, paint); | 
|  | } | 
|  | TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep); | 
|  |  | 
|  | static void DrawVerticesShaderTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | SkPoint pts[4]; | 
|  | pts[0].set(0, 0); | 
|  | pts[1].set(SkIntToScalar(kWidth), 0); | 
|  | pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight)); | 
|  | pts[3].set(0, SkIntToScalar(kHeight)); | 
|  | SkPaint paint; | 
|  | SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap, | 
|  | SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); | 
|  | paint.setShader(shader)->unref(); | 
|  | canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts, | 
|  | NULL, NULL, NULL, 0, paint); | 
|  | } | 
|  | // NYI: issue 240. | 
|  | TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep); | 
|  |  | 
|  | static void DrawPictureTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | SkPictureRecorder recorder; | 
|  | SkCanvas* testCanvas = recorder.beginRecording(kWidth, kHeight, NULL, 0); | 
|  | testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1)); | 
|  | testCanvas->clipRect(kTestRect); | 
|  | testCanvas->drawRect(kTestRect, kTestPaint); | 
|  | SkAutoTUnref<SkPicture> testPicture(recorder.endRecording()); | 
|  |  | 
|  | canvas->drawPicture(testPicture); | 
|  | } | 
|  | TEST_STEP(DrawPicture, DrawPictureTestStep); | 
|  |  | 
|  | static void SaveRestoreTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | int baseSaveCount = canvas->getSaveCount(); | 
|  | int n = canvas->save(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), | 
|  | testStep->assertMessage()); | 
|  | canvas->save(); | 
|  | canvas->save(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(), | 
|  | testStep->assertMessage()); | 
|  | canvas->restoreToCount(baseSaveCount + 1); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(), | 
|  | testStep->assertMessage()); | 
|  |  | 
|  | // should this pin to 1, or be a no-op, or crash? | 
|  | canvas->restoreToCount(0); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(), | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(SaveRestore, SaveRestoreTestStep); | 
|  |  | 
|  | static void DrawLayerTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | canvas->save(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | canvas->restore(); | 
|  |  | 
|  | const SkRect* bounds = NULL;    // null means include entire bounds | 
|  | const SkPaint* paint = NULL; | 
|  |  | 
|  | canvas->saveLayer(bounds, paint); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  |  | 
|  | canvas->saveLayer(bounds, paint); | 
|  | canvas->saveLayer(bounds, paint); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | canvas->restore(); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | canvas->restore(); | 
|  | // now layer count should be 0 | 
|  | REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(), | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | TEST_STEP(DrawLayer, DrawLayerTestStep); | 
|  |  | 
|  | static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | // This test step challenges the TestDeferredCanvasStateConsistency | 
|  | // test cases because the opaque paint can trigger an optimization | 
|  | // that discards previously recorded commands. The challenge is to maintain | 
|  | // correct clip and matrix stack state. | 
|  | canvas->resetMatrix(); | 
|  | canvas->rotate(SkIntToScalar(30)); | 
|  | canvas->save(); | 
|  | canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); | 
|  | canvas->save(); | 
|  | canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); | 
|  | SkPaint paint; | 
|  | paint.setColor(0xFFFFFFFF); | 
|  | canvas->drawPaint(paint); | 
|  | canvas->restore(); | 
|  | canvas->restore(); | 
|  | } | 
|  | TEST_STEP(NestedSaveRestoreWithSolidPaint, \ | 
|  | NestedSaveRestoreWithSolidPaintTestStep); | 
|  |  | 
|  | static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, | 
|  | skiatest::Reporter*, | 
|  | CanvasTestStep*) { | 
|  | // This test step challenges the TestDeferredCanvasStateConsistency | 
|  | // test case because the canvas flush on a deferred canvas will | 
|  | // reset the recording session. The challenge is to maintain correct | 
|  | // clip and matrix stack state on the playback canvas. | 
|  | canvas->resetMatrix(); | 
|  | canvas->rotate(SkIntToScalar(30)); | 
|  | canvas->save(); | 
|  | canvas->translate(SkIntToScalar(2), SkIntToScalar(1)); | 
|  | canvas->save(); | 
|  | canvas->scale(SkIntToScalar(3), SkIntToScalar(3)); | 
|  | canvas->drawRect(kTestRect,kTestPaint); | 
|  | canvas->flush(); | 
|  | canvas->restore(); | 
|  | canvas->restore(); | 
|  | } | 
|  | TEST_STEP(NestedSaveRestoreWithFlush, \ | 
|  | NestedSaveRestoreWithFlushTestStep); | 
|  |  | 
|  | static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, | 
|  | const SkCanvas* canvas1, | 
|  | const SkCanvas* canvas2, | 
|  | CanvasTestStep* testStep) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() == | 
|  | canvas2->getDeviceSize(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() == | 
|  | canvas2->getSaveCount(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() == | 
|  | canvas2->isDrawingToLayer(), testStep->assertMessage()); | 
|  |  | 
|  | SkRect bounds1, bounds2; | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2), | 
|  | testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2, | 
|  | testStep->assertMessage()); | 
|  |  | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() == | 
|  | canvas2->getDrawFilter(), testStep->assertMessage()); | 
|  | SkIRect deviceBounds1, deviceBounds2; | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | canvas1->getClipDeviceBounds(&deviceBounds1) == | 
|  | canvas2->getClipDeviceBounds(&deviceBounds2), | 
|  | testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() == | 
|  | canvas2->getTotalMatrix(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage()); | 
|  |  | 
|  | // The following test code is commented out because the test fails when | 
|  | // the canvas is an SkPictureRecord or SkDeferredCanvas | 
|  | // Issue: http://code.google.com/p/skia/issues/detail?id=498 | 
|  | // Also, creating a LayerIter on an SkProxyCanvas crashes | 
|  | // Issue: http://code.google.com/p/skia/issues/detail?id=499 | 
|  | /* | 
|  | SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false); | 
|  | SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false); | 
|  | while (!layerIter1.done() && !layerIter2.done()) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() == | 
|  | layerIter2.matrix(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() == | 
|  | layerIter2.clip(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() == | 
|  | layerIter2.paint(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() == | 
|  | layerIter2.x(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() == | 
|  | layerIter2.y(), testStep->assertMessage()); | 
|  | layerIter1.next(); | 
|  | layerIter2.next(); | 
|  | } | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(), | 
|  | testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(), | 
|  | testStep->assertMessage()); | 
|  | */ | 
|  | } | 
|  |  | 
|  | // The following class groups static functions that need to access | 
|  | // the privates members of SkPictureRecord | 
|  | class SkPictureTester { | 
|  | private: | 
|  | static int EQ(const SkFlatData* a, const SkFlatData* b) { | 
|  | return *a == *b; | 
|  | } | 
|  |  | 
|  | static void AssertFlattenedObjectsEqual( | 
|  | SkPictureRecord* referenceRecord, | 
|  | SkPictureRecord* testRecord, | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  |  | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | referenceRecord->fBitmapHeap->count() == | 
|  | testRecord->fBitmapHeap->count(), testStep->assertMessage()); | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | referenceRecord->fPaints.count() == | 
|  | testRecord->fPaints.count(), testStep->assertMessage()); | 
|  | for (int i = 0; i < referenceRecord->fPaints.count(); ++i) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | EQ(referenceRecord->fPaints[i], testRecord->fPaints[i]), | 
|  | testStep->assertMessage()); | 
|  | } | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | !referenceRecord->fPathHeap == !testRecord->fPathHeap, | 
|  | testStep->assertMessage()); | 
|  | // The following tests are commented out because they currently | 
|  | // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507 | 
|  | /* | 
|  | if (referenceRecord->fPathHeap) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | referenceRecord->fPathHeap->count() == | 
|  | testRecord->fPathHeap->count(), | 
|  | testStep->assertMessage()); | 
|  | for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) { | 
|  | REPORTER_ASSERT_MESSAGE(reporter, | 
|  | (*referenceRecord->fPathHeap)[i] == | 
|  | (*testRecord->fPathHeap)[i], testStep->assertMessage()); | 
|  | } | 
|  | } | 
|  | */ | 
|  |  | 
|  | } | 
|  |  | 
|  | public: | 
|  |  | 
|  | static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep, | 
|  | uint32_t recordFlags) { | 
|  | // Verify that when a test step is executed twice, no extra resources | 
|  | // are flattened during the second execution | 
|  | testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat); | 
|  | SkPictureRecorder referenceRecorder; | 
|  | SkCanvas* referenceCanvas = | 
|  | referenceRecorder.DEPRECATED_beginRecording(kWidth, kHeight, NULL, recordFlags); | 
|  | testStep->draw(referenceCanvas, reporter); | 
|  |  | 
|  | SkPictureRecorder testRecorder; | 
|  | SkCanvas* testCanvas = | 
|  | testRecorder.DEPRECATED_beginRecording(kWidth, kHeight, NULL, recordFlags); | 
|  | testStep->draw(testCanvas, reporter); | 
|  | testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat); | 
|  | testStep->draw(testCanvas, reporter); | 
|  |  | 
|  | SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(referenceCanvas); | 
|  | SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(testCanvas); | 
|  | testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat); | 
|  | AssertFlattenedObjectsEqual(referenceRecord, testRecord, | 
|  | reporter, testStep); | 
|  | } | 
|  | }; | 
|  |  | 
|  | static void TestPdfDevice(skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | SkISize pageSize = SkISize::Make(kWidth, kHeight); | 
|  | SkPDFDevice device(pageSize, pageSize, SkMatrix::I()); | 
|  | SkCanvas canvas(&device); | 
|  | testStep->setAssertMessageFormat(kPdfAssertMessageFormat); | 
|  | testStep->draw(&canvas, reporter); | 
|  | SkPDFDocument doc; | 
|  | doc.appendPage(&device); | 
|  | SkDynamicMemoryWStream stream; | 
|  | doc.emitPDF(&stream); | 
|  | } | 
|  |  | 
|  | // The following class groups static functions that need to access | 
|  | // the privates members of SkDeferredCanvas | 
|  | class SkDeferredCanvasTester { | 
|  | public: | 
|  | static void TestDeferredCanvasStateConsistency( | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep, | 
|  | const SkCanvas& referenceCanvas, bool silent) { | 
|  |  | 
|  | SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF)); | 
|  | SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(surface.get())); | 
|  |  | 
|  | testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat); | 
|  | testStep->draw(deferredCanvas, reporter); | 
|  | testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, deferredCanvas, &referenceCanvas, | 
|  | testStep); | 
|  |  | 
|  | if (silent) { | 
|  | deferredCanvas->silentFlush(); | 
|  | } else { | 
|  | deferredCanvas->flush(); | 
|  | } | 
|  |  | 
|  | testStep->setAssertMessageFormat( | 
|  | silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat : | 
|  | kDeferredPostFlushPlaybackAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, | 
|  | deferredCanvas->immediateCanvas(), | 
|  | &referenceCanvas, testStep); | 
|  |  | 
|  | // Verified that deferred canvas state is not affected by flushing | 
|  | // pending draw operations | 
|  |  | 
|  | // The following test code is commented out because it currently fails. | 
|  | // Issue: http://code.google.com/p/skia/issues/detail?id=496 | 
|  | /* | 
|  | testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas, | 
|  | testStep); | 
|  | */ | 
|  | } | 
|  | }; | 
|  |  | 
|  | // unused | 
|  | static void TestProxyCanvasStateConsistency( | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep, | 
|  | const SkCanvas& referenceCanvas) { | 
|  |  | 
|  | SkBitmap indirectStore; | 
|  | createBitmap(&indirectStore, 0xFFFFFFFF); | 
|  | SkCanvas indirectCanvas(indirectStore); | 
|  | SkProxyCanvas proxyCanvas(&indirectCanvas); | 
|  | testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat); | 
|  | testStep->draw(&proxyCanvas, reporter); | 
|  | // Verify that the SkProxyCanvas reports consitent state | 
|  | testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas, | 
|  | testStep); | 
|  | // Verify that the indirect canvas reports consitent state | 
|  | testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas, | 
|  | testStep); | 
|  | } | 
|  |  | 
|  | // unused | 
|  | static void TestNWayCanvasStateConsistency( | 
|  | skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep, | 
|  | const SkCanvas& referenceCanvas) { | 
|  |  | 
|  | SkBitmap indirectStore1; | 
|  | createBitmap(&indirectStore1, 0xFFFFFFFF); | 
|  | SkCanvas indirectCanvas1(indirectStore1); | 
|  |  | 
|  | SkBitmap indirectStore2; | 
|  | createBitmap(&indirectStore2, 0xFFFFFFFF); | 
|  | SkCanvas indirectCanvas2(indirectStore2); | 
|  |  | 
|  | SkISize canvasSize = referenceCanvas.getDeviceSize(); | 
|  | SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height()); | 
|  | nWayCanvas.addCanvas(&indirectCanvas1); | 
|  | nWayCanvas.addCanvas(&indirectCanvas2); | 
|  |  | 
|  | testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat); | 
|  | testStep->draw(&nWayCanvas, reporter); | 
|  | // Verify that the SkProxyCanvas reports consitent state | 
|  | testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas, | 
|  | testStep); | 
|  | // Verify that the indirect canvases report consitent state | 
|  | testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas, | 
|  | testStep); | 
|  | testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat); | 
|  | AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas, | 
|  | testStep); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * This sub-test verifies that the test step passes when executed | 
|  | * with SkCanvas and with classes derrived from SkCanvas. It also verifies | 
|  | * that the all canvas derivatives report the same state as an SkCanvas | 
|  | * after having executed the test step. | 
|  | */ | 
|  | static void TestOverrideStateConsistency(skiatest::Reporter* reporter, | 
|  | CanvasTestStep* testStep) { | 
|  | SkBitmap referenceStore; | 
|  | createBitmap(&referenceStore, 0xFFFFFFFF); | 
|  | SkCanvas referenceCanvas(referenceStore); | 
|  | testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat); | 
|  | testStep->draw(&referenceCanvas, reporter); | 
|  |  | 
|  | SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false); | 
|  |  | 
|  | SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true); | 
|  |  | 
|  | // The following test code is disabled because SkProxyCanvas is | 
|  | // missing a lot of virtual overrides on get* methods, which are used | 
|  | // to verify canvas state. | 
|  | // Issue: http://code.google.com/p/skia/issues/detail?id=500 | 
|  |  | 
|  | if (false) { // avoid bit rot, suppress warning | 
|  | TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas); | 
|  | } | 
|  |  | 
|  | // The following test code is disabled because SkNWayCanvas does not | 
|  | // report correct clipping and device bounds information | 
|  | // Issue: http://code.google.com/p/skia/issues/detail?id=501 | 
|  |  | 
|  | if (false) { // avoid bit rot, suppress warning | 
|  | TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas); | 
|  | } | 
|  |  | 
|  | if (false) { // avoid bit rot, suppress warning | 
|  | test_clipVisitor(reporter, &referenceCanvas); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void test_newraster(skiatest::Reporter* reporter) { | 
|  | SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); | 
|  | SkCanvas* canvas = SkCanvas::NewRaster(info); | 
|  | REPORTER_ASSERT(reporter, canvas); | 
|  |  | 
|  | SkImageInfo info2; | 
|  | size_t rowBytes; | 
|  | const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes); | 
|  | REPORTER_ASSERT(reporter, addr); | 
|  | REPORTER_ASSERT(reporter, info == info2); | 
|  | for (int y = 0; y < info.height(); ++y) { | 
|  | for (int x = 0; x < info.width(); ++x) { | 
|  | REPORTER_ASSERT(reporter, 0 == addr[x]); | 
|  | } | 
|  | addr = (const SkPMColor*)((const char*)addr + rowBytes); | 
|  | } | 
|  | SkDELETE(canvas); | 
|  |  | 
|  | // now try a deliberately bad info | 
|  | info.fWidth = -1; | 
|  | REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); | 
|  |  | 
|  | // too big | 
|  | info.fWidth = 1 << 30; | 
|  | info.fHeight = 1 << 30; | 
|  | REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); | 
|  |  | 
|  | // not a valid pixel type | 
|  | info.fWidth = info.fHeight = 10; | 
|  | info.fColorType = kUnknown_SkColorType; | 
|  | REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRaster(info)); | 
|  |  | 
|  | // We should succeed with a zero-sized valid info | 
|  | info = SkImageInfo::MakeN32Premul(0, 0); | 
|  | canvas = SkCanvas::NewRaster(info); | 
|  | REPORTER_ASSERT(reporter, canvas); | 
|  | SkDELETE(canvas); | 
|  | } | 
|  |  | 
|  | DEF_TEST(Canvas, reporter) { | 
|  | // Init global here because bitmap pixels cannot be alocated during | 
|  | // static initialization | 
|  | kTestBitmap = testBitmap(); | 
|  |  | 
|  | for (int testStep = 0; testStep < testStepArray().count(); testStep++) { | 
|  | TestOverrideStateConsistency(reporter, testStepArray()[testStep]); | 
|  | SkPictureTester::TestPictureFlattenedObjectReuse(reporter, | 
|  | testStepArray()[testStep], 0); | 
|  | if (testStepArray()[testStep]->enablePdfTesting()) { | 
|  | TestPdfDevice(reporter, testStepArray()[testStep]); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Explicitly call reset(), so we don't leak the pixels (since kTestBitmap is a global) | 
|  | kTestBitmap.reset(); | 
|  |  | 
|  | test_newraster(reporter); | 
|  | } |