Home | History | Annotate | Download | only in tests
      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 "SkClipStack.h"
     49 #include "SkDevice.h"
     50 #include "SkDocument.h"
     51 #include "SkMatrix.h"
     52 #include "SkNWayCanvas.h"
     53 #include "SkPaint.h"
     54 #include "SkPaintFilterCanvas.h"
     55 #include "SkPath.h"
     56 #include "SkPicture.h"
     57 #include "SkPictureRecord.h"
     58 #include "SkPictureRecorder.h"
     59 #include "SkRect.h"
     60 #include "SkRegion.h"
     61 #include "SkShader.h"
     62 #include "SkStream.h"
     63 #include "SkSurface.h"
     64 #include "SkTemplates.h"
     65 #include "SkTDArray.h"
     66 #include "Test.h"
     67 
     68 static const int kWidth = 2, kHeight = 2;
     69 
     70 static void createBitmap(SkBitmap* bm, SkColor color) {
     71     bm->allocN32Pixels(kWidth, kHeight);
     72     bm->eraseColor(color);
     73 }
     74 
     75 ///////////////////////////////////////////////////////////////////////////////
     76 // Constants used by test steps
     77 const SkPoint kTestPoints[] = {
     78     {SkIntToScalar(0), SkIntToScalar(0)},
     79     {SkIntToScalar(2), SkIntToScalar(1)},
     80     {SkIntToScalar(0), SkIntToScalar(2)}
     81 };
     82 const SkPoint kTestPoints2[] = {
     83     { SkIntToScalar(0), SkIntToScalar(1) },
     84     { SkIntToScalar(1), SkIntToScalar(1) },
     85     { SkIntToScalar(2), SkIntToScalar(1) },
     86     { SkIntToScalar(3), SkIntToScalar(1) },
     87     { SkIntToScalar(4), SkIntToScalar(1) },
     88     { SkIntToScalar(5), SkIntToScalar(1) },
     89     { SkIntToScalar(6), SkIntToScalar(1) },
     90     { SkIntToScalar(7), SkIntToScalar(1) },
     91     { SkIntToScalar(8), SkIntToScalar(1) },
     92     { SkIntToScalar(9), SkIntToScalar(1) },
     93     { SkIntToScalar(10), SkIntToScalar(1) }
     94 };
     95 
     96 struct TestData {
     97 public:
     98     TestData()
     99     : fRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
    100                                  SkIntToScalar(2), SkIntToScalar(1)))
    101     , fMatrix(TestMatrix())
    102     , fPath(TestPath())
    103     , fNearlyZeroLengthPath(TestNearlyZeroLengthPath())
    104     , fIRect(SkIRect::MakeXYWH(0, 0, 2, 1))
    105     , fRegion(TestRegion())
    106     , fColor(0x01020304)
    107     , fPoints(kTestPoints)
    108     , fPointCount(3)
    109     , fWidth(2)
    110     , fHeight(2)
    111     , fText("Hello World")
    112     , fPoints2(kTestPoints2)
    113     , fBitmap(TestBitmap())
    114     { }
    115 
    116     SkRect fRect;
    117     SkMatrix fMatrix;
    118     SkPath fPath;
    119     SkPath fNearlyZeroLengthPath;
    120     SkIRect fIRect;
    121     SkRegion fRegion;
    122     SkColor fColor;
    123     SkPaint fPaint;
    124     const SkPoint* fPoints;
    125     size_t fPointCount;
    126     int fWidth;
    127     int fHeight;
    128     SkString fText;
    129     const SkPoint* fPoints2;
    130     SkBitmap fBitmap;
    131 
    132 private:
    133     static SkMatrix TestMatrix() {
    134         SkMatrix matrix;
    135         matrix.reset();
    136         matrix.setScale(SkIntToScalar(2), SkIntToScalar(3));
    137 
    138         return matrix;
    139     }
    140     static SkPath TestPath() {
    141         SkPath path;
    142         path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
    143                                       SkIntToScalar(2), SkIntToScalar(1)));
    144         return path;
    145     }
    146     static SkPath TestNearlyZeroLengthPath() {
    147         SkPath path;
    148         SkPoint pt1 = { 0, 0 };
    149         SkPoint pt2 = { 0, SK_ScalarNearlyZero };
    150         SkPoint pt3 = { SkIntToScalar(1), 0 };
    151         SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 };
    152         path.moveTo(pt1);
    153         path.lineTo(pt2);
    154         path.lineTo(pt3);
    155         path.lineTo(pt4);
    156         return path;
    157     }
    158     static SkRegion TestRegion() {
    159         SkRegion region;
    160         SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1);
    161         region.setRect(rect);
    162         return region;
    163     }
    164     static SkBitmap TestBitmap() {
    165         SkBitmap bitmap;
    166         createBitmap(&bitmap, 0x05060708);
    167         return bitmap;
    168     }
    169 };
    170 
    171 static bool equal_clips(const SkCanvas& a, const SkCanvas& b) {
    172     if (a.isClipEmpty()) {
    173         return b.isClipEmpty();
    174     }
    175     if (!a.isClipRect()) {
    176         // this is liberally true, since we don't expose a way to know this exactly (for non-rects)
    177         return !b.isClipRect();
    178     }
    179     SkIRect ar, br;
    180     a.getClipDeviceBounds(&ar);
    181     b.getClipDeviceBounds(&br);
    182     return ar == br;
    183 }
    184 
    185 class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor {
    186 public:
    187     Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {}
    188 
    189     void clipRect(const SkRect& r, SkRegion::Op op, bool aa) override {
    190         fTarget->clipRect(r, op, aa);
    191     }
    192     void clipRRect(const SkRRect& r, SkRegion::Op op, bool aa) override {
    193         fTarget->clipRRect(r, op, aa);
    194     }
    195     void clipPath(const SkPath& p, SkRegion::Op op, bool aa) override {
    196         fTarget->clipPath(p, op, aa);
    197     }
    198 
    199 private:
    200     SkCanvas* fTarget;
    201 };
    202 
    203 static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) {
    204     SkISize size = canvas->getDeviceSize();
    205 
    206     SkBitmap bm;
    207     bm.setInfo(SkImageInfo::MakeN32Premul(size.width(), size.height()));
    208     SkCanvas c(bm);
    209 
    210     Canvas2CanvasClipVisitor visitor(&c);
    211     canvas->replayClips(&visitor);
    212 
    213     REPORTER_ASSERT(reporter, equal_clips(c, *canvas));
    214 }
    215 
    216 static void test_clipstack(skiatest::Reporter* reporter) {
    217     // The clipstack is refcounted, and needs to be able to out-live the canvas if a client has
    218     // ref'd it.
    219     const SkClipStack* cs = nullptr;
    220     {
    221         SkCanvas canvas(10, 10);
    222         cs = SkRef(canvas.getClipStack());
    223     }
    224     REPORTER_ASSERT(reporter, cs->unique());
    225     cs->unref();
    226 }
    227 
    228 // Format strings that describe the test context.  The %s token is where
    229 // the name of the test step is inserted.  The context is required for
    230 // disambiguating the error in the case of failures that are reported in
    231 // functions that are called multiple times in different contexts (test
    232 // cases and test steps).
    233 static const char* const kDefaultAssertMessageFormat = "%s";
    234 static const char* const kCanvasDrawAssertMessageFormat =
    235     "Drawing test step %s with SkCanvas";
    236 static const char* const kNWayDrawAssertMessageFormat =
    237     "Drawing test step %s with SkNWayCanvas";
    238 static const char* const kNWayStateAssertMessageFormat =
    239     "test step %s, SkNWayCanvas state consistency";
    240 static const char* const kNWayIndirect1StateAssertMessageFormat =
    241     "test step %s, SkNWayCanvas indirect canvas 1 state consistency";
    242 static const char* const kNWayIndirect2StateAssertMessageFormat =
    243     "test step %s, SkNWayCanvas indirect canvas 2 state consistency";
    244 static const char* const kPdfAssertMessageFormat =
    245     "PDF sanity check failed %s";
    246 
    247 class CanvasTestStep;
    248 static SkTDArray<CanvasTestStep*>& testStepArray() {
    249     static SkTDArray<CanvasTestStep*> theTests;
    250     return theTests;
    251 }
    252 
    253 class CanvasTestStep {
    254 public:
    255     CanvasTestStep(bool fEnablePdfTesting = true) {
    256         *testStepArray().append() = this;
    257         fAssertMessageFormat = kDefaultAssertMessageFormat;
    258         this->fEnablePdfTesting = fEnablePdfTesting;
    259     }
    260     virtual ~CanvasTestStep() { }
    261 
    262     virtual void draw(SkCanvas*, const TestData&, skiatest::Reporter*) = 0;
    263     virtual const char* name() const = 0;
    264 
    265     const char* assertMessage() {
    266         fAssertMessage.printf(fAssertMessageFormat, name());
    267         return fAssertMessage.c_str();
    268     }
    269 
    270     void setAssertMessageFormat(const char* format) {
    271         fAssertMessageFormat = format;
    272     }
    273 
    274     bool enablePdfTesting() { return fEnablePdfTesting; }
    275 
    276 private:
    277     SkString fAssertMessage;
    278     const char* fAssertMessageFormat;
    279     bool fEnablePdfTesting;
    280 };
    281 
    282 ///////////////////////////////////////////////////////////////////////////////
    283 // Macros for defining test steps
    284 
    285 #define TEST_STEP(NAME, FUNCTION)                                       \
    286 class NAME##_TestStep : public CanvasTestStep{                          \
    287 public:                                                                 \
    288     virtual void draw(SkCanvas* canvas, const TestData& d,       \
    289         skiatest::Reporter* reporter) {                                 \
    290         FUNCTION (canvas, d, reporter, this);                    \
    291     }                                                                   \
    292     virtual const char* name() const {return #NAME ;}                   \
    293 };                                                                      \
    294 static NAME##_TestStep NAME##_TestStepInstance;
    295 
    296 #define TEST_STEP_NO_PDF(NAME, FUNCTION)                                \
    297 class NAME##_TestStep : public CanvasTestStep{                          \
    298 public:                                                                 \
    299     NAME##_TestStep() : CanvasTestStep(false) {}                        \
    300     virtual void draw(SkCanvas* canvas, const TestData& d,       \
    301         skiatest::Reporter* reporter) {                                 \
    302         FUNCTION (canvas, d, reporter, this);                    \
    303     }                                                                   \
    304     virtual const char* name() const {return #NAME ;}                   \
    305 };                                                                      \
    306 static NAME##_TestStep NAME##_TestStepInstance;
    307 
    308 #define SIMPLE_TEST_STEP(NAME, CALL)                                    \
    309 static void NAME##TestStep(SkCanvas* canvas, const TestData& d,  \
    310     skiatest::Reporter*, CanvasTestStep*) {                             \
    311     canvas-> CALL ;                                                     \
    312 }                                                                       \
    313 TEST_STEP(NAME, NAME##TestStep )
    314 
    315 #define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL)                           \
    316 static void NAME##TestStep(SkCanvas* canvas, const TestData& d,     \
    317     skiatest::Reporter*, CanvasTestStep* testStep) {                       \
    318     REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL ,                      \
    319         testStep->assertMessage());                                        \
    320 }                                                                          \
    321 TEST_STEP(NAME, NAME##TestStep )
    322 
    323 
    324 ///////////////////////////////////////////////////////////////////////////////
    325 // Basic test steps for most virtual methods in SkCanvas that draw or affect
    326 // the state of the canvas.
    327 
    328 SIMPLE_TEST_STEP(Translate, translate(SkIntToScalar(1), SkIntToScalar(2)));
    329 SIMPLE_TEST_STEP(Scale, scale(SkIntToScalar(1), SkIntToScalar(2)));
    330 SIMPLE_TEST_STEP(Rotate, rotate(SkIntToScalar(1)));
    331 SIMPLE_TEST_STEP(Skew, skew(SkIntToScalar(1), SkIntToScalar(2)));
    332 SIMPLE_TEST_STEP(Concat, concat(d.fMatrix));
    333 SIMPLE_TEST_STEP(SetMatrix, setMatrix(d.fMatrix));
    334 SIMPLE_TEST_STEP(ClipRect, clipRect(d.fRect));
    335 SIMPLE_TEST_STEP(ClipPath, clipPath(d.fPath));
    336 SIMPLE_TEST_STEP(ClipRegion, clipRegion(d.fRegion, SkRegion::kReplace_Op));
    337 SIMPLE_TEST_STEP(Clear, clear(d.fColor));
    338 
    339 ///////////////////////////////////////////////////////////////////////////////
    340 // Complex test steps
    341 
    342 static void SaveMatrixClipStep(SkCanvas* canvas, const TestData& d,
    343                                skiatest::Reporter* reporter, CanvasTestStep* testStep) {
    344     int saveCount = canvas->getSaveCount();
    345     canvas->save();
    346     canvas->translate(SkIntToScalar(1), SkIntToScalar(2));
    347     canvas->clipRegion(d.fRegion);
    348     canvas->restore();
    349     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
    350         testStep->assertMessage());
    351     REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(),
    352         testStep->assertMessage());
    353 //    REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage());
    354 }
    355 TEST_STEP(SaveMatrixClip, SaveMatrixClipStep);
    356 
    357 static void SaveLayerStep(SkCanvas* canvas, const TestData& d,
    358                           skiatest::Reporter* reporter, CanvasTestStep* testStep) {
    359     int saveCount = canvas->getSaveCount();
    360     canvas->saveLayer(nullptr, nullptr);
    361     canvas->restore();
    362     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
    363         testStep->assertMessage());
    364 }
    365 TEST_STEP(SaveLayer, SaveLayerStep);
    366 
    367 static void BoundedSaveLayerStep(SkCanvas* canvas, const TestData& d,
    368                                  skiatest::Reporter* reporter, CanvasTestStep* testStep) {
    369     int saveCount = canvas->getSaveCount();
    370     canvas->saveLayer(&d.fRect, nullptr);
    371     canvas->restore();
    372     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
    373         testStep->assertMessage());
    374 }
    375 TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep);
    376 
    377 static void PaintSaveLayerStep(SkCanvas* canvas, const TestData& d,
    378                                skiatest::Reporter* reporter, CanvasTestStep* testStep) {
    379     int saveCount = canvas->getSaveCount();
    380     canvas->saveLayer(nullptr, &d.fPaint);
    381     canvas->restore();
    382     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
    383         testStep->assertMessage());
    384 }
    385 TEST_STEP(PaintSaveLayer, PaintSaveLayerStep);
    386 
    387 static void TwoClipOpsStep(SkCanvas* canvas, const TestData& d,
    388                            skiatest::Reporter*, CanvasTestStep*) {
    389     // This test exercises a functionality in SkPicture that leads to the
    390     // recording of restore offset placeholders.  This test will trigger an
    391     // assertion at playback time if the placeholders are not properly
    392     // filled when the recording ends.
    393     canvas->clipRect(d.fRect);
    394     canvas->clipRegion(d.fRegion);
    395 }
    396 TEST_STEP(TwoClipOps, TwoClipOpsStep);
    397 
    398 // exercise fix for http://code.google.com/p/skia/issues/detail?id=560
    399 // ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero')
    400 static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, const TestData& d,
    401                                              skiatest::Reporter*, CanvasTestStep*) {
    402     SkPaint paint;
    403     paint.setStrokeWidth(SkIntToScalar(1));
    404     paint.setStyle(SkPaint::kStroke_Style);
    405 
    406     canvas->drawPath(d.fNearlyZeroLengthPath, paint);
    407 }
    408 TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep);
    409 
    410 static void DrawVerticesShaderTestStep(SkCanvas* canvas, const TestData& d,
    411                                        skiatest::Reporter*, CanvasTestStep*) {
    412     SkPoint pts[4];
    413     pts[0].set(0, 0);
    414     pts[1].set(SkIntToScalar(d.fWidth), 0);
    415     pts[2].set(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight));
    416     pts[3].set(0, SkIntToScalar(d.fHeight));
    417     SkPaint paint;
    418     SkShader* shader = SkShader::CreateBitmapShader(d.fBitmap,
    419         SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
    420     paint.setShader(shader)->unref();
    421     canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts,
    422                          nullptr, nullptr, nullptr, 0, paint);
    423 }
    424 // NYI: issue 240.
    425 TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep);
    426 
    427 static void DrawPictureTestStep(SkCanvas* canvas, const TestData& d,
    428                                 skiatest::Reporter*, CanvasTestStep*) {
    429     SkPictureRecorder recorder;
    430     SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight),
    431                                                    nullptr, 0);
    432     testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
    433     testCanvas->clipRect(d.fRect);
    434     testCanvas->drawRect(d.fRect, d.fPaint);
    435     SkAutoTUnref<SkPicture> testPicture(recorder.endRecording());
    436 
    437     canvas->drawPicture(testPicture);
    438 }
    439 TEST_STEP(DrawPicture, DrawPictureTestStep);
    440 
    441 static void SaveRestoreTestStep(SkCanvas* canvas, const TestData& d,
    442                                 skiatest::Reporter* reporter, CanvasTestStep* testStep) {
    443     int baseSaveCount = canvas->getSaveCount();
    444     int n = canvas->save();
    445     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage());
    446     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(),
    447         testStep->assertMessage());
    448     canvas->save();
    449     canvas->save();
    450     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(),
    451         testStep->assertMessage());
    452     canvas->restoreToCount(baseSaveCount + 1);
    453     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(),
    454         testStep->assertMessage());
    455 
    456     // should this pin to 1, or be a no-op, or crash?
    457     canvas->restoreToCount(0);
    458     REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
    459         testStep->assertMessage());
    460 }
    461 TEST_STEP(SaveRestore, SaveRestoreTestStep);
    462 
    463 static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, const TestData& d,
    464                                                     skiatest::Reporter*, CanvasTestStep*) {
    465     // This test step challenges the TestDeferredCanvasStateConsistency
    466     // test cases because the opaque paint can trigger an optimization
    467     // that discards previously recorded commands. The challenge is to maintain
    468     // correct clip and matrix stack state.
    469     canvas->resetMatrix();
    470     canvas->rotate(SkIntToScalar(30));
    471     canvas->save();
    472     canvas->translate(SkIntToScalar(2), SkIntToScalar(1));
    473     canvas->save();
    474     canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
    475     SkPaint paint;
    476     paint.setColor(0xFFFFFFFF);
    477     canvas->drawPaint(paint);
    478     canvas->restore();
    479     canvas->restore();
    480 }
    481 TEST_STEP(NestedSaveRestoreWithSolidPaint, \
    482     NestedSaveRestoreWithSolidPaintTestStep);
    483 
    484 static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, const TestData& d,
    485                                                skiatest::Reporter*, CanvasTestStep*) {
    486     // This test step challenges the TestDeferredCanvasStateConsistency
    487     // test case because the canvas flush on a deferred canvas will
    488     // reset the recording session. The challenge is to maintain correct
    489     // clip and matrix stack state on the playback canvas.
    490     canvas->resetMatrix();
    491     canvas->rotate(SkIntToScalar(30));
    492     canvas->save();
    493     canvas->translate(SkIntToScalar(2), SkIntToScalar(1));
    494     canvas->save();
    495     canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
    496     canvas->drawRect(d.fRect,d.fPaint);
    497     canvas->flush();
    498     canvas->restore();
    499     canvas->restore();
    500 }
    501 TEST_STEP(NestedSaveRestoreWithFlush, NestedSaveRestoreWithFlushTestStep);
    502 
    503 static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, const TestData& d,
    504                                     const SkCanvas* canvas1, const SkCanvas* canvas2,
    505                                     CanvasTestStep* testStep) {
    506     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() ==
    507         canvas2->getDeviceSize(), testStep->assertMessage());
    508     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() ==
    509         canvas2->getSaveCount(), testStep->assertMessage());
    510 
    511     SkRect bounds1, bounds2;
    512     REPORTER_ASSERT_MESSAGE(reporter,
    513         canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2),
    514         testStep->assertMessage());
    515     REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
    516                             testStep->assertMessage());
    517 
    518 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
    519     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() ==
    520         canvas2->getDrawFilter(), testStep->assertMessage());
    521 #endif
    522 
    523     SkIRect deviceBounds1, deviceBounds2;
    524     REPORTER_ASSERT_MESSAGE(reporter,
    525         canvas1->getClipDeviceBounds(&deviceBounds1) ==
    526         canvas2->getClipDeviceBounds(&deviceBounds2),
    527         testStep->assertMessage());
    528     REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2, testStep->assertMessage());
    529     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() ==
    530         canvas2->getTotalMatrix(), testStep->assertMessage());
    531     REPORTER_ASSERT_MESSAGE(reporter, equal_clips(*canvas1, *canvas2), testStep->assertMessage());
    532 
    533     SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false);
    534     SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false);
    535     while (!layerIter1.done() && !layerIter2.done()) {
    536         REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() ==
    537             layerIter2.matrix(), testStep->assertMessage());
    538         REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() ==
    539             layerIter2.clip(), testStep->assertMessage());
    540         REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() ==
    541             layerIter2.paint(), testStep->assertMessage());
    542         REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() ==
    543             layerIter2.x(), testStep->assertMessage());
    544         REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() ==
    545             layerIter2.y(), testStep->assertMessage());
    546         layerIter1.next();
    547         layerIter2.next();
    548     }
    549     REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(),
    550         testStep->assertMessage());
    551     REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(),
    552         testStep->assertMessage());
    553 
    554 }
    555 
    556 static void TestPdfDevice(skiatest::Reporter* reporter,
    557                           const TestData& d,
    558                           CanvasTestStep* testStep) {
    559     SkDynamicMemoryWStream outStream;
    560     SkAutoTUnref<SkDocument> doc(SkDocument::CreatePDF(&outStream));
    561 #if SK_SUPPORT_PDF
    562     REPORTER_ASSERT(reporter, doc);
    563 #else
    564     REPORTER_ASSERT(reporter, !doc);
    565 #endif  // SK_SUPPORT_PDF
    566     if (!doc) {
    567         return;
    568     }
    569     SkCanvas* canvas = doc->beginPage(SkIntToScalar(d.fWidth),
    570                                       SkIntToScalar(d.fHeight));
    571     REPORTER_ASSERT(reporter, canvas);
    572     testStep->setAssertMessageFormat(kPdfAssertMessageFormat);
    573     testStep->draw(canvas, d, reporter);
    574 
    575     REPORTER_ASSERT(reporter, doc->close());
    576 }
    577 
    578 // unused
    579 static void TestNWayCanvasStateConsistency(
    580     skiatest::Reporter* reporter,
    581     const TestData& d,
    582     CanvasTestStep* testStep,
    583     const SkCanvas& referenceCanvas) {
    584 
    585     SkBitmap indirectStore1;
    586     createBitmap(&indirectStore1, 0xFFFFFFFF);
    587     SkCanvas indirectCanvas1(indirectStore1);
    588 
    589     SkBitmap indirectStore2;
    590     createBitmap(&indirectStore2, 0xFFFFFFFF);
    591     SkCanvas indirectCanvas2(indirectStore2);
    592 
    593     SkISize canvasSize = referenceCanvas.getDeviceSize();
    594     SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height());
    595     nWayCanvas.addCanvas(&indirectCanvas1);
    596     nWayCanvas.addCanvas(&indirectCanvas2);
    597 
    598     testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat);
    599     testStep->draw(&nWayCanvas, d, reporter);
    600     // Verify that the SkNWayCanvas reports consitent state
    601     testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat);
    602     AssertCanvasStatesEqual(reporter, d, &nWayCanvas, &referenceCanvas, testStep);
    603     // Verify that the indirect canvases report consitent state
    604     testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat);
    605     AssertCanvasStatesEqual(reporter, d, &indirectCanvas1, &referenceCanvas, testStep);
    606     testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat);
    607     AssertCanvasStatesEqual(reporter, d, &indirectCanvas2, &referenceCanvas, testStep);
    608 }
    609 
    610 /*
    611  * This sub-test verifies that the test step passes when executed
    612  * with SkCanvas and with classes derrived from SkCanvas. It also verifies
    613  * that the all canvas derivatives report the same state as an SkCanvas
    614  * after having executed the test step.
    615  */
    616 static void TestOverrideStateConsistency(skiatest::Reporter* reporter, const TestData& d,
    617                                          CanvasTestStep* testStep) {
    618     SkBitmap referenceStore;
    619     createBitmap(&referenceStore, 0xFFFFFFFF);
    620     SkCanvas referenceCanvas(referenceStore);
    621     testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat);
    622     testStep->draw(&referenceCanvas, d, reporter);
    623 
    624     // The following test code is disabled because SkNWayCanvas does not
    625     // report correct clipping and device bounds information
    626     // Issue: http://code.google.com/p/skia/issues/detail?id=501
    627 
    628     if (false) { // avoid bit rot, suppress warning
    629         TestNWayCanvasStateConsistency(reporter, d, testStep, referenceCanvas);
    630     }
    631 
    632     if (false) { // avoid bit rot, suppress warning
    633         test_clipVisitor(reporter, &referenceCanvas);
    634     }
    635     test_clipstack(reporter);
    636 }
    637 
    638 static void test_newraster(skiatest::Reporter* reporter) {
    639     SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
    640     const size_t minRowBytes = info.minRowBytes();
    641     const size_t size = info.getSafeSize(minRowBytes);
    642     SkAutoTMalloc<SkPMColor> storage(size);
    643     SkPMColor* baseAddr = storage.get();
    644     sk_bzero(baseAddr, size);
    645 
    646     SkCanvas* canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
    647     REPORTER_ASSERT(reporter, canvas);
    648 
    649     SkImageInfo info2;
    650     size_t rowBytes;
    651     const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes);
    652     REPORTER_ASSERT(reporter, addr);
    653     REPORTER_ASSERT(reporter, info == info2);
    654     REPORTER_ASSERT(reporter, minRowBytes == rowBytes);
    655     for (int y = 0; y < info.height(); ++y) {
    656         for (int x = 0; x < info.width(); ++x) {
    657             REPORTER_ASSERT(reporter, 0 == addr[x]);
    658         }
    659         addr = (const SkPMColor*)((const char*)addr + rowBytes);
    660     }
    661     delete canvas;
    662 
    663     // now try a deliberately bad info
    664     info = info.makeWH(-1, info.height());
    665     REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
    666 
    667     // too big
    668     info = info.makeWH(1 << 30, 1 << 30);
    669     REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
    670 
    671     // not a valid pixel type
    672     info = SkImageInfo::Make(10, 10, kUnknown_SkColorType, info.alphaType());
    673     REPORTER_ASSERT(reporter, nullptr == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
    674 
    675     // We should succeed with a zero-sized valid info
    676     info = SkImageInfo::MakeN32Premul(0, 0);
    677     canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
    678     REPORTER_ASSERT(reporter, canvas);
    679     delete canvas;
    680 }
    681 
    682 DEF_TEST(Canvas, reporter) {
    683     TestData d;
    684 
    685     for (int testStep = 0; testStep < testStepArray().count(); testStep++) {
    686         TestOverrideStateConsistency(reporter, d, testStepArray()[testStep]);
    687         if (testStepArray()[testStep]->enablePdfTesting()) {
    688             TestPdfDevice(reporter, d, testStepArray()[testStep]);
    689         }
    690     }
    691 
    692     test_newraster(reporter);
    693 }
    694 
    695 DEF_TEST(Canvas_SaveState, reporter) {
    696     SkCanvas canvas(10, 10);
    697     REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount());
    698 
    699     int n = canvas.save();
    700     REPORTER_ASSERT(reporter, 1 == n);
    701     REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount());
    702 
    703     n = canvas.saveLayer(nullptr, nullptr);
    704     REPORTER_ASSERT(reporter, 2 == n);
    705     REPORTER_ASSERT(reporter, 3 == canvas.getSaveCount());
    706 
    707     canvas.restore();
    708     REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount());
    709     canvas.restore();
    710     REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount());
    711 }
    712 
    713 DEF_TEST(Canvas_ClipEmptyPath, reporter) {
    714     SkCanvas canvas(10, 10);
    715     canvas.save();
    716     SkPath path;
    717     canvas.clipPath(path);
    718     canvas.restore();
    719     canvas.save();
    720     path.moveTo(5, 5);
    721     canvas.clipPath(path);
    722     canvas.restore();
    723     canvas.save();
    724     path.moveTo(7, 7);
    725     canvas.clipPath(path);  // should not assert here
    726     canvas.restore();
    727 }
    728 
    729 namespace {
    730 
    731 class MockFilterCanvas : public SkPaintFilterCanvas {
    732 public:
    733     MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
    734 
    735 protected:
    736     bool onFilter(SkTCopyOnFirstWrite<SkPaint>*, Type) const override { return true; }
    737 
    738 private:
    739     typedef SkPaintFilterCanvas INHERITED;
    740 };
    741 
    742 } // anonymous namespace
    743 
    744 // SkPaintFilterCanvas should inherit the initial target canvas state.
    745 DEF_TEST(PaintFilterCanvas_ConsistentState, reporter) {
    746     SkCanvas canvas(100, 100);
    747     canvas.clipRect(SkRect::MakeXYWH(12.7f, 12.7f, 75, 75));
    748     canvas.scale(0.5f, 0.75f);
    749 
    750     SkRect clip1, clip2;
    751 
    752     MockFilterCanvas filterCanvas(&canvas);
    753     REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
    754     REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
    755     REPORTER_ASSERT(reporter, clip1 == clip2);
    756 
    757     filterCanvas.clipRect(SkRect::MakeXYWH(30.5f, 30.7f, 100, 100));
    758     filterCanvas.scale(0.75f, 0.5f);
    759     REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
    760     REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
    761     REPORTER_ASSERT(reporter, clip1 == clip2);
    762 }
    763