C++11 override should now be supported by all of {bots,Chrome,Android,Mozilla}
[platform/upstream/libSkiaSharp.git] / tests / CanvasTest.cpp
1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 /*  Description:
9  *      This test defines a series of elementatry test steps that perform
10  *      a single or a small group of canvas API calls. Each test step is
11  *      used in several test cases that verify that different types of SkCanvas
12  *      flavors and derivatives pass it and yield consistent behavior. The
13  *      test cases analyse results that are queryable through the API. They do
14  *      not look at rendering results.
15  *
16  *  Adding test stepss:
17  *      The general pattern for creating a new test step is to write a test
18  *      function of the form:
19  *
20  *          static void MyTestStepFunction(SkCanvas* canvas,
21  *                                         skiatest::Reporter* reporter,
22  *                                         CanvasTestStep* testStep)
23  *          {
24  *              canvas->someCanvasAPImethod();
25  *              (...)
26  *              REPORTER_ASSERT_MESSAGE(reporter, (...), \
27  *                  testStep->assertMessage());
28  *          }
29  *
30  *      The definition of the test step function should be followed by an
31  *      invocation of the TEST_STEP macro, which generates a class and
32  *      instance for the test step:
33  *
34  *          TEST_STEP(MyTestStep, MyTestStepFunction)
35  *
36  *      There are also short hand macros for defining simple test steps
37  *      in a single line of code.  A simple test step is a one that is made
38  *      of a single canvas API call.
39  *
40  *          SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod());
41  *
42  *      There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that
43  *      works the same way as SIMPLE_TEST_STEP, and additionally verifies
44  *      that the invoked method returns a non-zero value.
45  */
46 #include "SkBitmap.h"
47 #include "SkCanvas.h"
48 #include "SkDeferredCanvas.h"
49 #include "SkDevice.h"
50 #include "SkDocument.h"
51 #include "SkMatrix.h"
52 #include "SkNWayCanvas.h"
53 #include "SkPaint.h"
54 #include "SkPath.h"
55 #include "SkPicture.h"
56 #include "SkPictureRecord.h"
57 #include "SkPictureRecorder.h"
58 #include "SkRect.h"
59 #include "SkRegion.h"
60 #include "SkShader.h"
61 #include "SkStream.h"
62 #include "SkSurface.h"
63 #include "SkTDArray.h"
64 #include "Test.h"
65
66 static const int kWidth = 2, kHeight = 2;
67
68 static void createBitmap(SkBitmap* bm, SkColor color) {
69     bm->allocN32Pixels(kWidth, kHeight);
70     bm->eraseColor(color);
71 }
72
73 static SkSurface* createSurface(SkColor color) {
74     SkSurface* surface = SkSurface::NewRasterN32Premul(kWidth, kHeight);
75     surface->getCanvas()->clear(color);
76     return surface;
77 }
78
79 ///////////////////////////////////////////////////////////////////////////////
80 // Constants used by test steps
81 const SkPoint kTestPoints[] = {
82     {SkIntToScalar(0), SkIntToScalar(0)},
83     {SkIntToScalar(2), SkIntToScalar(1)},
84     {SkIntToScalar(0), SkIntToScalar(2)}
85 };
86 const SkPoint kTestPoints2[] = {
87     { SkIntToScalar(0), SkIntToScalar(1) },
88     { SkIntToScalar(1), SkIntToScalar(1) },
89     { SkIntToScalar(2), SkIntToScalar(1) },
90     { SkIntToScalar(3), SkIntToScalar(1) },
91     { SkIntToScalar(4), SkIntToScalar(1) },
92     { SkIntToScalar(5), SkIntToScalar(1) },
93     { SkIntToScalar(6), SkIntToScalar(1) },
94     { SkIntToScalar(7), SkIntToScalar(1) },
95     { SkIntToScalar(8), SkIntToScalar(1) },
96     { SkIntToScalar(9), SkIntToScalar(1) },
97     { SkIntToScalar(10), SkIntToScalar(1) }
98 };
99
100 struct TestData {
101 public:
102     TestData()
103     : fRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
104                                  SkIntToScalar(2), SkIntToScalar(1)))
105     , fMatrix(TestMatrix())
106     , fPath(TestPath())
107     , fNearlyZeroLengthPath(TestNearlyZeroLengthPath())
108     , fIRect(SkIRect::MakeXYWH(0, 0, 2, 1))
109     , fRegion(TestRegion())
110     , fColor(0x01020304)
111     , fPoints(kTestPoints)
112     , fPointCount(3)
113     , fWidth(2)
114     , fHeight(2)
115     , fText("Hello World")
116     , fPoints2(kTestPoints2)
117     , fBitmap(TestBitmap())
118     { }
119
120     SkRect fRect;
121     SkMatrix fMatrix;;
122     SkPath fPath;
123     SkPath fNearlyZeroLengthPath;
124     SkIRect fIRect;
125     SkRegion fRegion;
126     SkColor fColor;
127     SkPaint fPaint;
128     const SkPoint* fPoints;
129     size_t fPointCount;
130     int fWidth;
131     int fHeight;
132     SkString fText;
133     const SkPoint* fPoints2;
134     SkBitmap fBitmap;
135
136 private:
137     static SkMatrix TestMatrix() {
138         SkMatrix matrix;
139         matrix.reset();
140         matrix.setScale(SkIntToScalar(2), SkIntToScalar(3));
141
142         return matrix;
143     }
144     static SkPath TestPath() {
145         SkPath path;
146         path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
147                                       SkIntToScalar(2), SkIntToScalar(1)));
148         return path;
149     }
150     static SkPath TestNearlyZeroLengthPath() {
151         SkPath path;
152         SkPoint pt1 = { 0, 0 };
153         SkPoint pt2 = { 0, SK_ScalarNearlyZero };
154         SkPoint pt3 = { SkIntToScalar(1), 0 };
155         SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 };
156         path.moveTo(pt1);
157         path.lineTo(pt2);
158         path.lineTo(pt3);
159         path.lineTo(pt4);
160         return path;
161     }
162     static SkRegion TestRegion() {
163         SkRegion region;
164         SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1);
165         region.setRect(rect);
166         return region;
167     }
168     static SkBitmap TestBitmap() {
169         SkBitmap bitmap;
170         createBitmap(&bitmap, 0x05060708);
171         return bitmap;
172     }
173 };
174
175 static bool equal_clips(const SkCanvas& a, const SkCanvas& b) {
176     if (a.isClipEmpty()) {
177         return b.isClipEmpty();
178     }
179     if (!a.isClipRect()) {
180         // this is liberally true, since we don't expose a way to know this exactly (for non-rects)
181         return !b.isClipRect();
182     }
183     SkIRect ar, br;
184     a.getClipDeviceBounds(&ar);
185     b.getClipDeviceBounds(&br);
186     return ar == br;
187 }
188
189 class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor {
190 public:
191     Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {}
192
193     void clipRect(const SkRect& r, SkRegion::Op op, bool aa) override {
194         fTarget->clipRect(r, op, aa);
195     }
196     void clipRRect(const SkRRect& r, SkRegion::Op op, bool aa) override {
197         fTarget->clipRRect(r, op, aa);
198     }
199     void clipPath(const SkPath& p, SkRegion::Op op, bool aa) override {
200         fTarget->clipPath(p, op, aa);
201     }
202
203 private:
204     SkCanvas* fTarget;
205 };
206
207 static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) {
208     SkISize size = canvas->getDeviceSize();
209
210     SkBitmap bm;
211     bm.setInfo(SkImageInfo::MakeN32Premul(size.width(), size.height()));
212     SkCanvas c(bm);
213
214     Canvas2CanvasClipVisitor visitor(&c);
215     canvas->replayClips(&visitor);
216
217     REPORTER_ASSERT(reporter, equal_clips(c, *canvas));
218 }
219
220 // Format strings that describe the test context.  The %s token is where
221 // the name of the test step is inserted.  The context is required for
222 // disambiguating the error in the case of failures that are reported in
223 // functions that are called multiple times in different contexts (test
224 // cases and test steps).
225 static const char* const kDefaultAssertMessageFormat = "%s";
226 static const char* const kCanvasDrawAssertMessageFormat =
227     "Drawing test step %s with SkCanvas";
228 static const char* const kDeferredDrawAssertMessageFormat =
229     "Drawing test step %s with SkDeferredCanvas";
230 static const char* const kNWayDrawAssertMessageFormat =
231     "Drawing test step %s with SkNWayCanvas";
232 static const char* const kDeferredPreFlushAssertMessageFormat =
233     "test step %s, SkDeferredCanvas state consistency before flush";
234 static const char* const kDeferredPostFlushPlaybackAssertMessageFormat =
235     "test step %s, SkDeferredCanvas playback canvas state consistency after flush";
236 static const char* const kDeferredPostSilentFlushPlaybackAssertMessageFormat =
237     "test step %s, SkDeferredCanvas playback canvas state consistency after silent flush";
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 SIMPLE_TEST_STEP(BeginGroup, beginCommentGroup(d.fText.c_str()));
339 SIMPLE_TEST_STEP(AddComment, addComment(d.fText.c_str(), d.fText.c_str()));
340 SIMPLE_TEST_STEP(EndGroup, endCommentGroup());
341
342 ///////////////////////////////////////////////////////////////////////////////
343 // Complex test steps
344
345 static void SaveMatrixClipStep(SkCanvas* canvas, const TestData& d,
346                                skiatest::Reporter* reporter, CanvasTestStep* testStep) {
347     int saveCount = canvas->getSaveCount();
348     canvas->save();
349     canvas->translate(SkIntToScalar(1), SkIntToScalar(2));
350     canvas->clipRegion(d.fRegion);
351     canvas->restore();
352     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
353         testStep->assertMessage());
354     REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalMatrix().isIdentity(),
355         testStep->assertMessage());
356 //    REPORTER_ASSERT_MESSAGE(reporter, canvas->getTotalClip() != kTestRegion, testStep->assertMessage());
357 }
358 TEST_STEP(SaveMatrixClip, SaveMatrixClipStep);
359
360 static void SaveLayerStep(SkCanvas* canvas, const TestData& d,
361                           skiatest::Reporter* reporter, CanvasTestStep* testStep) {
362     int saveCount = canvas->getSaveCount();
363     canvas->saveLayer(NULL, NULL);
364     canvas->restore();
365     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
366         testStep->assertMessage());
367 }
368 TEST_STEP(SaveLayer, SaveLayerStep);
369
370 static void BoundedSaveLayerStep(SkCanvas* canvas, const TestData& d,
371                                  skiatest::Reporter* reporter, CanvasTestStep* testStep) {
372     int saveCount = canvas->getSaveCount();
373     canvas->saveLayer(&d.fRect, NULL);
374     canvas->restore();
375     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
376         testStep->assertMessage());
377 }
378 TEST_STEP(BoundedSaveLayer, BoundedSaveLayerStep);
379
380 static void PaintSaveLayerStep(SkCanvas* canvas, const TestData& d,
381                                skiatest::Reporter* reporter, CanvasTestStep* testStep) {
382     int saveCount = canvas->getSaveCount();
383     canvas->saveLayer(NULL, &d.fPaint);
384     canvas->restore();
385     REPORTER_ASSERT_MESSAGE(reporter, canvas->getSaveCount() == saveCount,
386         testStep->assertMessage());
387 }
388 TEST_STEP(PaintSaveLayer, PaintSaveLayerStep);
389
390 static void TwoClipOpsStep(SkCanvas* canvas, const TestData& d,
391                            skiatest::Reporter*, CanvasTestStep*) {
392     // This test exercises a functionality in SkPicture that leads to the
393     // recording of restore offset placeholders.  This test will trigger an
394     // assertion at playback time if the placeholders are not properly
395     // filled when the recording ends.
396     canvas->clipRect(d.fRect);
397     canvas->clipRegion(d.fRegion);
398 }
399 TEST_STEP(TwoClipOps, TwoClipOpsStep);
400
401 // exercise fix for http://code.google.com/p/skia/issues/detail?id=560
402 // ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero')
403 static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas, const TestData& d,
404                                              skiatest::Reporter*, CanvasTestStep*) {
405     SkPaint paint;
406     paint.setStrokeWidth(SkIntToScalar(1));
407     paint.setStyle(SkPaint::kStroke_Style);
408
409     canvas->drawPath(d.fNearlyZeroLengthPath, paint);
410 }
411 TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep);
412
413 static void DrawVerticesShaderTestStep(SkCanvas* canvas, const TestData& d,
414                                        skiatest::Reporter*, CanvasTestStep*) {
415     SkPoint pts[4];
416     pts[0].set(0, 0);
417     pts[1].set(SkIntToScalar(d.fWidth), 0);
418     pts[2].set(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight));
419     pts[3].set(0, SkIntToScalar(d.fHeight));
420     SkPaint paint;
421     SkShader* shader = SkShader::CreateBitmapShader(d.fBitmap,
422         SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
423     paint.setShader(shader)->unref();
424     canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts,
425                          NULL, NULL, NULL, 0, paint);
426 }
427 // NYI: issue 240.
428 TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep);
429
430 static void DrawPictureTestStep(SkCanvas* canvas, const TestData& d,
431                                 skiatest::Reporter*, CanvasTestStep*) {
432     SkPictureRecorder recorder;
433     SkCanvas* testCanvas = recorder.beginRecording(SkIntToScalar(d.fWidth), SkIntToScalar(d.fHeight),
434                                                    NULL, 0);
435     testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
436     testCanvas->clipRect(d.fRect);
437     testCanvas->drawRect(d.fRect, d.fPaint);
438     SkAutoTUnref<SkPicture> testPicture(recorder.endRecording());
439
440     canvas->drawPicture(testPicture);
441 }
442 TEST_STEP(DrawPicture, DrawPictureTestStep);
443
444 static void SaveRestoreTestStep(SkCanvas* canvas, const TestData& d,
445                                 skiatest::Reporter* reporter, CanvasTestStep* testStep) {
446     int baseSaveCount = canvas->getSaveCount();
447     int n = canvas->save();
448     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount == n, testStep->assertMessage());
449     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(),
450         testStep->assertMessage());
451     canvas->save();
452     canvas->save();
453     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 3 == canvas->getSaveCount(),
454         testStep->assertMessage());
455     canvas->restoreToCount(baseSaveCount + 1);
456     REPORTER_ASSERT_MESSAGE(reporter, baseSaveCount + 1 == canvas->getSaveCount(),
457         testStep->assertMessage());
458
459     // should this pin to 1, or be a no-op, or crash?
460     canvas->restoreToCount(0);
461     REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
462         testStep->assertMessage());
463 }
464 TEST_STEP(SaveRestore, SaveRestoreTestStep);
465
466 static void NestedSaveRestoreWithSolidPaintTestStep(SkCanvas* canvas, const TestData& d,
467                                                     skiatest::Reporter*, CanvasTestStep*) {
468     // This test step challenges the TestDeferredCanvasStateConsistency
469     // test cases because the opaque paint can trigger an optimization
470     // that discards previously recorded commands. The challenge is to maintain
471     // correct clip and matrix stack state.
472     canvas->resetMatrix();
473     canvas->rotate(SkIntToScalar(30));
474     canvas->save();
475     canvas->translate(SkIntToScalar(2), SkIntToScalar(1));
476     canvas->save();
477     canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
478     SkPaint paint;
479     paint.setColor(0xFFFFFFFF);
480     canvas->drawPaint(paint);
481     canvas->restore();
482     canvas->restore();
483 }
484 TEST_STEP(NestedSaveRestoreWithSolidPaint, \
485     NestedSaveRestoreWithSolidPaintTestStep);
486
487 static void NestedSaveRestoreWithFlushTestStep(SkCanvas* canvas, const TestData& d,
488                                                skiatest::Reporter*, CanvasTestStep*) {
489     // This test step challenges the TestDeferredCanvasStateConsistency
490     // test case because the canvas flush on a deferred canvas will
491     // reset the recording session. The challenge is to maintain correct
492     // clip and matrix stack state on the playback canvas.
493     canvas->resetMatrix();
494     canvas->rotate(SkIntToScalar(30));
495     canvas->save();
496     canvas->translate(SkIntToScalar(2), SkIntToScalar(1));
497     canvas->save();
498     canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
499     canvas->drawRect(d.fRect,d.fPaint);
500     canvas->flush();
501     canvas->restore();
502     canvas->restore();
503 }
504 TEST_STEP(NestedSaveRestoreWithFlush, NestedSaveRestoreWithFlushTestStep);
505
506 static void AssertCanvasStatesEqual(skiatest::Reporter* reporter, const TestData& d,
507                                     const SkCanvas* canvas1, const SkCanvas* canvas2,
508                                     CanvasTestStep* testStep) {
509     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() ==
510         canvas2->getDeviceSize(), testStep->assertMessage());
511     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() ==
512         canvas2->getSaveCount(), testStep->assertMessage());
513
514     SkRect bounds1, bounds2;
515     REPORTER_ASSERT_MESSAGE(reporter,
516         canvas1->getClipBounds(&bounds1) == canvas2->getClipBounds(&bounds2),
517         testStep->assertMessage());
518     REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
519                             testStep->assertMessage());
520
521     REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() ==
522         canvas2->getDrawFilter(), testStep->assertMessage());
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     SkCanvas* canvas = doc->beginPage(SkIntToScalar(d.fWidth),
562                                       SkIntToScalar(d.fHeight));
563     REPORTER_ASSERT(reporter, canvas);
564     testStep->setAssertMessageFormat(kPdfAssertMessageFormat);
565     testStep->draw(canvas, d, reporter);
566
567     REPORTER_ASSERT(reporter, doc->close());
568 }
569
570 // The following class groups static functions that need to access
571 // the privates members of SkDeferredCanvas
572 class SkDeferredCanvasTester {
573 public:
574     static void TestDeferredCanvasStateConsistency(
575         skiatest::Reporter* reporter,
576         const TestData& d,
577         CanvasTestStep* testStep,
578         const SkCanvas& referenceCanvas, bool silent) {
579
580         SkAutoTUnref<SkSurface> surface(createSurface(0xFFFFFFFF));
581         SkAutoTUnref<SkDeferredCanvas> deferredCanvas(SkDeferredCanvas::Create(surface.get()));
582
583         testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat);
584         testStep->draw(deferredCanvas, d, reporter);
585         testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat);
586         AssertCanvasStatesEqual(reporter, d, deferredCanvas, &referenceCanvas, testStep);
587
588         if (silent) {
589             deferredCanvas->silentFlush();
590         } else {
591             deferredCanvas->flush();
592         }
593
594         testStep->setAssertMessageFormat(
595             silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat :
596             kDeferredPostFlushPlaybackAssertMessageFormat);
597         AssertCanvasStatesEqual(reporter, d, deferredCanvas->immediateCanvas(),
598                                 &referenceCanvas, testStep);
599
600         // Verified that deferred canvas state is not affected by flushing
601         // pending draw operations
602
603         // The following test code is commented out because it currently fails.
604         // Issue: http://code.google.com/p/skia/issues/detail?id=496
605         /*
606         testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat);
607         AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
608             testStep);
609         */
610     }
611 };
612
613 // unused
614 static void TestNWayCanvasStateConsistency(
615     skiatest::Reporter* reporter,
616     const TestData& d,
617     CanvasTestStep* testStep,
618     const SkCanvas& referenceCanvas) {
619
620     SkBitmap indirectStore1;
621     createBitmap(&indirectStore1, 0xFFFFFFFF);
622     SkCanvas indirectCanvas1(indirectStore1);
623
624     SkBitmap indirectStore2;
625     createBitmap(&indirectStore2, 0xFFFFFFFF);
626     SkCanvas indirectCanvas2(indirectStore2);
627
628     SkISize canvasSize = referenceCanvas.getDeviceSize();
629     SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height());
630     nWayCanvas.addCanvas(&indirectCanvas1);
631     nWayCanvas.addCanvas(&indirectCanvas2);
632
633     testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat);
634     testStep->draw(&nWayCanvas, d, reporter);
635     // Verify that the SkNWayCanvas reports consitent state
636     testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat);
637     AssertCanvasStatesEqual(reporter, d, &nWayCanvas, &referenceCanvas, testStep);
638     // Verify that the indirect canvases report consitent state
639     testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat);
640     AssertCanvasStatesEqual(reporter, d, &indirectCanvas1, &referenceCanvas, testStep);
641     testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat);
642     AssertCanvasStatesEqual(reporter, d, &indirectCanvas2, &referenceCanvas, testStep);
643 }
644
645 /*
646  * This sub-test verifies that the test step passes when executed
647  * with SkCanvas and with classes derrived from SkCanvas. It also verifies
648  * that the all canvas derivatives report the same state as an SkCanvas
649  * after having executed the test step.
650  */
651 static void TestOverrideStateConsistency(skiatest::Reporter* reporter, const TestData& d,
652                                          CanvasTestStep* testStep) {
653     SkBitmap referenceStore;
654     createBitmap(&referenceStore, 0xFFFFFFFF);
655     SkCanvas referenceCanvas(referenceStore);
656     testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat);
657     testStep->draw(&referenceCanvas, d, reporter);
658
659     SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, d, testStep, referenceCanvas, false);
660
661     SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, d, testStep, referenceCanvas, true);
662
663     // The following test code is disabled because SkNWayCanvas does not
664     // report correct clipping and device bounds information
665     // Issue: http://code.google.com/p/skia/issues/detail?id=501
666
667     if (false) { // avoid bit rot, suppress warning
668         TestNWayCanvasStateConsistency(reporter, d, testStep, referenceCanvas);
669     }
670
671     if (false) { // avoid bit rot, suppress warning
672         test_clipVisitor(reporter, &referenceCanvas);
673     }
674 }
675
676 static void test_newraster(skiatest::Reporter* reporter) {
677     SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10);
678     const size_t minRowBytes = info.minRowBytes();
679     const size_t size = info.getSafeSize(minRowBytes);
680     SkAutoMalloc storage(size);
681     SkPMColor* baseAddr = static_cast<SkPMColor*>(storage.get());
682     sk_bzero(baseAddr, size);
683
684     SkCanvas* canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
685     REPORTER_ASSERT(reporter, canvas);
686
687     SkImageInfo info2;
688     size_t rowBytes;
689     const SkPMColor* addr = (const SkPMColor*)canvas->peekPixels(&info2, &rowBytes);
690     REPORTER_ASSERT(reporter, addr);
691     REPORTER_ASSERT(reporter, info == info2);
692     REPORTER_ASSERT(reporter, minRowBytes == rowBytes);
693     for (int y = 0; y < info.height(); ++y) {
694         for (int x = 0; x < info.width(); ++x) {
695             REPORTER_ASSERT(reporter, 0 == addr[x]);
696         }
697         addr = (const SkPMColor*)((const char*)addr + rowBytes);
698     }
699     SkDELETE(canvas);
700
701     // now try a deliberately bad info
702     info = info.makeWH(-1, info.height());
703     REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
704
705     // too big
706     info = info.makeWH(1 << 30, 1 << 30);
707     REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
708
709     // not a valid pixel type
710     info = SkImageInfo::Make(10, 10, kUnknown_SkColorType, info.alphaType());
711     REPORTER_ASSERT(reporter, NULL == SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes));
712
713     // We should succeed with a zero-sized valid info
714     info = SkImageInfo::MakeN32Premul(0, 0);
715     canvas = SkCanvas::NewRasterDirect(info, baseAddr, minRowBytes);
716     REPORTER_ASSERT(reporter, canvas);
717     SkDELETE(canvas);
718 }
719
720 DEF_TEST(Canvas, reporter) {
721     TestData d;
722
723     for (int testStep = 0; testStep < testStepArray().count(); testStep++) {
724         TestOverrideStateConsistency(reporter, d, testStepArray()[testStep]);
725         if (testStepArray()[testStep]->enablePdfTesting()) {
726             TestPdfDevice(reporter, d, testStepArray()[testStep]);
727         }
728     }
729
730     test_newraster(reporter);
731 }
732
733 DEF_TEST(Canvas_SaveState, reporter) {
734     SkCanvas canvas(10, 10);
735     REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount());
736
737     int n = canvas.save();
738     REPORTER_ASSERT(reporter, 1 == n);
739     REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount());
740
741     n = canvas.saveLayer(NULL, NULL);
742     REPORTER_ASSERT(reporter, 2 == n);
743     REPORTER_ASSERT(reporter, 3 == canvas.getSaveCount());
744     
745     canvas.restore();
746     REPORTER_ASSERT(reporter, 2 == canvas.getSaveCount());
747     canvas.restore();
748     REPORTER_ASSERT(reporter, 1 == canvas.getSaveCount());
749 }
750
751 DEF_TEST(Canvas_ClipEmptyPath, reporter) {
752     SkCanvas canvas(10, 10);
753     canvas.save();
754     SkPath path;
755     canvas.clipPath(path);
756     canvas.restore();
757     canvas.save();
758     path.moveTo(5, 5);
759     canvas.clipPath(path);
760     canvas.restore();
761     canvas.save();
762     path.moveTo(7, 7);
763     canvas.clipPath(path);  // should not assert here
764     canvas.restore();
765 }