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
68static const int kWidth = 2, kHeight = 2;
69
70static void createBitmap(SkBitmap* bm, SkColor color) {
71    bm->allocN32Pixels(kWidth, kHeight);
72    bm->eraseColor(color);
73}
74
75///////////////////////////////////////////////////////////////////////////////
76// Constants used by test steps
77const SkPoint kTestPoints[] = {
78    {SkIntToScalar(0), SkIntToScalar(0)},
79    {SkIntToScalar(2), SkIntToScalar(1)},
80    {SkIntToScalar(0), SkIntToScalar(2)}
81};
82const 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
96struct TestData {
97public:
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
132private:
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
171static 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
185class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor {
186public:
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
199private:
200    SkCanvas* fTarget;
201};
202
203static 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
216static 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).
233static const char* const kDefaultAssertMessageFormat = "%s";
234static const char* const kCanvasDrawAssertMessageFormat =
235    "Drawing test step %s with SkCanvas";
236static const char* const kNWayDrawAssertMessageFormat =
237    "Drawing test step %s with SkNWayCanvas";
238static const char* const kNWayStateAssertMessageFormat =
239    "test step %s, SkNWayCanvas state consistency";
240static const char* const kNWayIndirect1StateAssertMessageFormat =
241    "test step %s, SkNWayCanvas indirect canvas 1 state consistency";
242static const char* const kNWayIndirect2StateAssertMessageFormat =
243    "test step %s, SkNWayCanvas indirect canvas 2 state consistency";
244static const char* const kPdfAssertMessageFormat =
245    "PDF sanity check failed %s";
246
247class CanvasTestStep;
248static SkTDArray<CanvasTestStep*>& testStepArray() {
249    static SkTDArray<CanvasTestStep*> theTests;
250    return theTests;
251}
252
253class CanvasTestStep {
254public:
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
276private:
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)                                       \
286class NAME##_TestStep : public CanvasTestStep{                          \
287public:                                                                 \
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};                                                                      \
294static NAME##_TestStep NAME##_TestStepInstance;
295
296#define TEST_STEP_NO_PDF(NAME, FUNCTION)                                \
297class NAME##_TestStep : public CanvasTestStep{                          \
298public:                                                                 \
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};                                                                      \
306static NAME##_TestStep NAME##_TestStepInstance;
307
308#define SIMPLE_TEST_STEP(NAME, CALL)                                    \
309static void NAME##TestStep(SkCanvas* canvas, const TestData& d,  \
310    skiatest::Reporter*, CanvasTestStep*) {                             \
311    canvas-> CALL ;                                                     \
312}                                                                       \
313TEST_STEP(NAME, NAME##TestStep )
314
315#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL)                           \
316static void NAME##TestStep(SkCanvas* canvas, const TestData& d,     \
317    skiatest::Reporter*, CanvasTestStep* testStep) {                       \
318    REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL ,                      \
319        testStep->assertMessage());                                        \
320}                                                                          \
321TEST_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
328SIMPLE_TEST_STEP(Translate, translate(SkIntToScalar(1), SkIntToScalar(2)));
329SIMPLE_TEST_STEP(Scale, scale(SkIntToScalar(1), SkIntToScalar(2)));
330SIMPLE_TEST_STEP(Rotate, rotate(SkIntToScalar(1)));
331SIMPLE_TEST_STEP(Skew, skew(SkIntToScalar(1), SkIntToScalar(2)));
332SIMPLE_TEST_STEP(Concat, concat(d.fMatrix));
333SIMPLE_TEST_STEP(SetMatrix, setMatrix(d.fMatrix));
334SIMPLE_TEST_STEP(ClipRect, clipRect(d.fRect));
335SIMPLE_TEST_STEP(ClipPath, clipPath(d.fPath));
336SIMPLE_TEST_STEP(ClipRegion, clipRegion(d.fRegion, SkRegion::kReplace_Op));
337SIMPLE_TEST_STEP(Clear, clear(d.fColor));
338
339///////////////////////////////////////////////////////////////////////////////
340// Complex test steps
341
342static 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}
355TEST_STEP(SaveMatrixClip, SaveMatrixClipStep);
356
357static 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}
365TEST_STEP(SaveLayer, SaveLayerStep);
366
367static 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}
375TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep);
376
377static 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}
385TEST_STEP(PaintSaveLayer, PaintSaveLayerStep);
386
387static 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}
396TEST_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')
400static 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}
408TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep);
409
410static 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.
425TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep);
426
427static 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}
439TEST_STEP(DrawPicture, DrawPictureTestStep);
440
441static 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}
461TEST_STEP(SaveRestore, SaveRestoreTestStep);
462
463static 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}
481TEST_STEP(NestedSaveRestoreWithSolidPaint, \
482    NestedSaveRestoreWithSolidPaintTestStep);
483
484static 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}
501TEST_STEP(NestedSaveRestoreWithFlush, NestedSaveRestoreWithFlushTestStep);
502
503static 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
556static 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
579static 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 */
616static 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
638static 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
682DEF_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
695DEF_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
713DEF_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
729namespace {
730
731class MockFilterCanvas : public SkPaintFilterCanvas {
732public:
733    MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
734
735protected:
736    bool onFilter(SkTCopyOnFirstWrite<SkPaint>*, Type) const override { return true; }
737
738private:
739    typedef SkPaintFilterCanvas INHERITED;
740};
741
742} // anonymous namespace
743
744// SkPaintFilterCanvas should inherit the initial target canvas state.
745DEF_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