CanvasTest.cpp revision e63793a2c8d2871bf7d95195be7b93ff669688d7
1
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9/*  Description:
10 *      This test defines a series of elementatry test steps that perform
11 *      a single or a small group of canvas API calls. Each test step is
12 *      used in several test cases that verify that different types of SkCanvas
13 *      flavors and derivatives pass it and yield consistent behavior. The
14 *      test cases analyse results that are queryable through the API. They do
15 *      not look at rendering results.
16 *
17 *  Adding test stepss:
18 *      The general pattern for creating a new test step is to write a test
19 *      function of the form:
20 *
21 *          static void MyTestStepFunction(SkCanvas* canvas,
22 *                                         skiatest::Reporter* reporter,
23 *                                         CanvasTestStep* testStep)
24 *          {
25 *              canvas->someCanvasAPImethod();
26 *              (...)
27 *              REPORTER_ASSERT_MESSAGE(reporter, (...), \
28 *                  testStep->assertMessage());
29 *          }
30 *
31 *      The definition of the test step function should be followed by an
32 *      invocation of the TEST_STEP macro, which generates a class and
33 *      instance for the test step:
34 *
35 *          TEST_STEP(MyTestStep, MyTestStepFunction)
36 *
37 *      There are also short hand macros for defining simple test steps
38 *      in a single line of code.  A simple test step is a one that is made
39 *      of a single canvas API call.
40 *
41 *          SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod());
42 *
43 *      There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that
44 *      works the same way as SIMPLE_TEST_STEP, and additionally verifies
45 *      that the invoked method returns a non-zero value.
46 */
47#include "SkBitmap.h"
48#include "SkCanvas.h"
49#include "SkDeferredCanvas.h"
50#include "SkDevice.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 "SkProxyCanvas.h"
58#include "SkRect.h"
59#include "SkRegion.h"
60#include "SkShader.h"
61#include "SkStream.h"
62#include "SkTDArray.h"
63#include "Test.h"
64
65static const int kWidth = 2;
66static const int kHeight = 2;
67// Maximum stream length for picture serialization
68static const size_t kMaxPictureBufferSize = 1024;
69
70// Format strings that describe the test context.  The %s token is where
71// the name of the test step is inserted.  The context is required for
72// disambiguating the error in the case of failures that are reported in
73// functions that are called multiple times in different contexts (test
74// cases and test steps).
75static const char* const kDefaultAssertMessageFormat = "%s";
76static const char* const kCanvasDrawAssertMessageFormat =
77    "Drawing test step %s with SkCanvas";
78static const char* const kPictureDrawAssertMessageFormat =
79    "Drawing test step %s with SkPicture";
80static const char* const kPictureSecondDrawAssertMessageFormat =
81    "Duplicate draw of test step %s with SkPicture";
82static const char* const kPictureReDrawAssertMessageFormat =
83    "Playing back test step %s from an SkPicture to another SkPicture";
84static const char* const kDeferredDrawAssertMessageFormat =
85    "Drawing test step %s with SkDeferredCanvas";
86static const char* const kProxyDrawAssertMessageFormat =
87    "Drawing test step %s with SkProxyCanvas";
88static const char* const kNWayDrawAssertMessageFormat =
89    "Drawing test step %s with SkNWayCanvas";
90static const char* const kRoundTripAssertMessageFormat =
91    "test step %s, SkPicture consistency after round trip";
92static const char* const kPictureRecoringAssertMessageFormat =
93    "test step %s, SkPicture state consistency after recording";
94static const char* const kPicturePlaybackAssertMessageFormat =
95    "test step %s, SkPicture state consistency in playback canvas";
96static const char* const kDeferredPreFlushAssertMessageFormat =
97    "test step %s, SkDeferredCanvas state consistency before flush";
98static const char* const kDeferredPostFlushAssertMessageFormat =
99    "test step %s, SkDeferredCanvas state consistency after flush";
100static const char* const kPictureResourceReuseMessageFormat =
101    "test step %s, SkPicture duplicate flattened object test";
102static const char* const kProxyStateAssertMessageFormat =
103    "test step %s, SkProxyCanvas state consistency";
104static const char* const kProxyIndirectStateAssertMessageFormat =
105    "test step %s, SkProxyCanvas indirect canvas state consistency";
106static const char* const kNWayStateAssertMessageFormat =
107    "test step %s, SkNWayCanvas state consistency";
108static const char* const kNWayIndirect1StateAssertMessageFormat =
109    "test step %s, SkNWayCanvas indirect canvas 1 state consistency";
110static const char* const kNWayIndirect2StateAssertMessageFormat =
111    "test step %s, SkNWayCanvas indirect canvas 2 state consistency";
112
113static void createBitmap(SkBitmap* bm, SkBitmap::Config config, SkColor color) {
114    bm->setConfig(config, kWidth, kHeight);
115    bm->allocPixels();
116    bm->eraseColor(color);
117}
118
119class CanvasTestStep;
120static SkTDArray<CanvasTestStep*>& testStepArray() {
121    static SkTDArray<CanvasTestStep*> theTests;
122    return theTests;
123}
124
125class CanvasTestStep {
126public:
127    CanvasTestStep() {
128        *testStepArray().append() = this;
129        fAssertMessageFormat = kDefaultAssertMessageFormat;
130    }
131    virtual ~CanvasTestStep() { }
132
133    virtual void draw(SkCanvas*, skiatest::Reporter*) = 0;
134    virtual const char* name() const = 0;
135
136    const char* assertMessage() {
137        fAssertMessage.printf(fAssertMessageFormat, name());
138        return fAssertMessage.c_str();
139    }
140
141    void setAssertMessageFormat(const char* format) {
142        fAssertMessageFormat = format;
143    }
144
145private:
146    SkString fAssertMessage;
147    const char* fAssertMessageFormat;
148};
149
150///////////////////////////////////////////////////////////////////////////////
151// Constants used by test steps
152
153const SkRect kTestRect =
154    SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
155                     SkIntToScalar(2), SkIntToScalar(1));
156static SkMatrix testMatrix() {
157    SkMatrix matrix;
158    matrix.reset();
159    matrix.setScale(SkIntToScalar(2), SkIntToScalar(3));
160    return matrix;
161}
162const SkMatrix kTestMatrix = testMatrix();
163static SkPath testPath() {
164    SkPath path;
165    path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
166                                  SkIntToScalar(2), SkIntToScalar(1)));
167    return path;
168}
169const SkPath kTestPath = testPath();
170static SkRegion testRegion() {
171    SkRegion region;
172    SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1);
173    region.setRect(rect);
174    return region;
175}
176const SkIRect kTestIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
177const SkRegion kTestRegion = testRegion();
178const SkColor kTestColor = 0x01020304;
179const SkPaint kTestPaint;
180const SkPoint kTestPoints[3] = {
181    {SkIntToScalar(0), SkIntToScalar(0)},
182    {SkIntToScalar(2), SkIntToScalar(1)},
183    {SkIntToScalar(0), SkIntToScalar(2)}
184};
185const size_t kTestPointCount = 3;
186static SkBitmap testBitmap() {
187    SkBitmap bitmap;
188    createBitmap(&bitmap, SkBitmap::kARGB_8888_Config, 0x05060708);
189    return bitmap;
190}
191SkBitmap kTestBitmap; // cannot be created during static init
192SkString kTestText("Hello World");
193SkPoint kTestPoint = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(1));
194
195///////////////////////////////////////////////////////////////////////////////
196// Macros for defining test steps
197
198#define TEST_STEP(NAME, FUNCTION)                                       \
199class NAME##_TestStep : public CanvasTestStep{                          \
200public:                                                                 \
201    virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \
202        FUNCTION (canvas, reporter, this);                              \
203    }                                                                   \
204    virtual const char* name() const {return #NAME ;}                   \
205};                                                                      \
206static NAME##_TestStep NAME##_TestStepInstance;
207
208#define SIMPLE_TEST_STEP(NAME, CALL)                              \
209static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \
210    CanvasTestStep*) {                                            \
211    canvas-> CALL ;                                               \
212}                                                                 \
213TEST_STEP(NAME, NAME##TestStep )
214
215#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL)                           \
216static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \
217    CanvasTestStep* testStep) {                                            \
218    REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL ,                      \
219        testStep->assertMessage());                                        \
220}                                                                          \
221TEST_STEP(NAME, NAME##TestStep )
222
223
224///////////////////////////////////////////////////////////////////////////////
225// Basic test steps for most virtual methods in SkCanvas that draw or affect
226// the state of the canvas.
227
228SIMPLE_TEST_STEP(SaveMatrix, save(SkCanvas::kMatrix_SaveFlag));
229SIMPLE_TEST_STEP(SaveClip, save(SkCanvas::kClip_SaveFlag));
230SIMPLE_TEST_STEP(SaveMatrixClip, save(SkCanvas::kMatrixClip_SaveFlag));
231SIMPLE_TEST_STEP(SaveLayer, saveLayer(NULL, NULL));
232SIMPLE_TEST_STEP(BoundedSaveLayer, saveLayer(&kTestRect, NULL));
233SIMPLE_TEST_STEP(PaintSaveLayer, saveLayer(NULL, &kTestPaint));
234SIMPLE_TEST_STEP_WITH_ASSERT(Translate,
235    translate(SkIntToScalar(1), SkIntToScalar(2)));
236SIMPLE_TEST_STEP_WITH_ASSERT(Scale,
237    scale(SkIntToScalar(1), SkIntToScalar(2)));
238SIMPLE_TEST_STEP_WITH_ASSERT(Rotate, rotate(SkIntToScalar(1)));
239SIMPLE_TEST_STEP_WITH_ASSERT(Skew,
240    skew(SkIntToScalar(1), SkIntToScalar(2)));
241SIMPLE_TEST_STEP_WITH_ASSERT(Concat, concat(kTestMatrix));
242SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix));
243SIMPLE_TEST_STEP_WITH_ASSERT(ClipRect, clipRect(kTestRect));
244SIMPLE_TEST_STEP_WITH_ASSERT(ClipPath, clipPath(kTestPath));
245SIMPLE_TEST_STEP_WITH_ASSERT(ClipRegion,
246    clipRegion(kTestRegion, SkRegion::kReplace_Op));
247SIMPLE_TEST_STEP(Clear, clear(kTestColor));
248SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint));
249SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode,
250    kTestPointCount, kTestPoints, kTestPaint));
251SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode,
252    kTestPointCount, kTestPoints, kTestPaint));
253SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode,
254    kTestPointCount, kTestPoints, kTestPaint));
255SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint));
256SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint));
257SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0));
258SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint));
259SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect,
260    NULL));
261SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap,
262    &kTestIRect, kTestRect, NULL));
263SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL,
264    kTestRect, &kTestPaint));
265SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix,
266    NULL));
267SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap,
268    kTestMatrix, &kTestPaint));
269SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect,
270    kTestRect, NULL));
271SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect,
272    kTestRect, &kTestPaint));
273SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL));
274SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint));
275SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(),
276    0, 1, kTestPaint));
277SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(),
278    kTestText.size(), &kTestPoint, kTestPaint));
279SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(),
280    kTestText.size(), kTestPath, NULL, kTestPaint));
281SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(),
282    kTestText.size(), kTestPath, &kTestMatrix, kTestPaint));
283SIMPLE_TEST_STEP(SetExternalMatrix, setExternalMatrix(&kTestMatrix));
284SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size()));
285
286///////////////////////////////////////////////////////////////////////////////
287// Complex test steps
288
289static void DrawVerticesShaderTestStep(SkCanvas* canvas,
290                                       skiatest::Reporter* reporter,
291                                       CanvasTestStep* testStep) {
292    SkPoint pts[4];
293    pts[0].set(0, 0);
294    pts[1].set(SkIntToScalar(kWidth), 0);
295    pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
296    pts[3].set(0, SkIntToScalar(kHeight));
297    SkPaint paint;
298    SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap,
299        SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
300    paint.setShader(shader)->unref();
301    canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts,
302                         NULL, NULL, NULL, 0, paint);
303}
304TEST_STEP(DrawVerticesShader, DrawVerticesShaderTestStep);
305
306static void DrawPictureTestStep(SkCanvas* canvas,
307                                skiatest::Reporter* reporter,
308                                CanvasTestStep* testStep) {
309    SkPicture* testPicture = SkNEW_ARGS(SkPicture, ());
310    SkAutoUnref aup(testPicture);
311    SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight);
312    testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
313    testCanvas->clipRect(kTestRect);
314    testCanvas->drawRect(kTestRect, kTestPaint);
315    canvas->drawPicture(*testPicture);
316}
317TEST_STEP(DrawPicture, DrawPictureTestStep);
318
319static void SaveRestoreTestStep(SkCanvas* canvas,
320                                skiatest::Reporter* reporter,
321                                CanvasTestStep* testStep) {
322    REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
323        testStep->assertMessage());
324    size_t n = canvas->save();
325    REPORTER_ASSERT_MESSAGE(reporter, 1 == n, testStep->assertMessage());
326    REPORTER_ASSERT_MESSAGE(reporter, 2 == canvas->getSaveCount(),
327        testStep->assertMessage());
328    canvas->save();
329    canvas->save();
330    REPORTER_ASSERT_MESSAGE(reporter, 4 == canvas->getSaveCount(),
331        testStep->assertMessage());
332    canvas->restoreToCount(2);
333    REPORTER_ASSERT_MESSAGE(reporter, 2 == canvas->getSaveCount(),
334        testStep->assertMessage());
335
336    // should this pin to 1, or be a no-op, or crash?
337    canvas->restoreToCount(0);
338    REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
339        testStep->assertMessage());
340}
341TEST_STEP(SaveRestore, SaveRestoreTestStep);
342
343static void DrawLayerTestStep(SkCanvas* canvas,
344                              skiatest::Reporter* reporter,
345                              CanvasTestStep* testStep) {
346    REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
347        testStep->assertMessage());
348    canvas->save();
349    REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
350        testStep->assertMessage());
351
352    const SkRect* bounds = NULL;    // null means include entire bounds
353    const SkPaint* paint = NULL;
354
355    canvas->saveLayer(bounds, paint);
356    REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
357        testStep->assertMessage());
358    canvas->restore();
359    REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
360        testStep->assertMessage());
361
362    canvas->saveLayer(bounds, paint);
363    canvas->saveLayer(bounds, paint);
364    REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
365        testStep->assertMessage());
366    canvas->restore();
367    REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
368        testStep->assertMessage());
369    canvas->restore();
370    // now layer count should be 0
371    REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
372        testStep->assertMessage());
373}
374TEST_STEP(DrawLayer, DrawLayerTestStep);
375
376static void AssertCanvasStatesEqual(skiatest::Reporter* reporter,
377                                    const SkCanvas* canvas1,
378                                    const SkCanvas* canvas2,
379                                    CanvasTestStep* testStep) {
380    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() ==
381        canvas2->getDeviceSize(), testStep->assertMessage());
382    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() ==
383        canvas2->getSaveCount(), testStep->assertMessage());
384    REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() ==
385        canvas2->isDrawingToLayer(), testStep->assertMessage());
386    SkRect bounds1, bounds2;
387    REPORTER_ASSERT_MESSAGE(reporter,
388        canvas1->getClipBounds(&bounds1, SkCanvas::kAA_EdgeType) ==
389        canvas2->getClipBounds(&bounds2, SkCanvas::kAA_EdgeType),
390        testStep->assertMessage());
391    REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
392        testStep->assertMessage());
393    REPORTER_ASSERT_MESSAGE(reporter,
394        canvas1->getClipBounds(&bounds1, SkCanvas::kBW_EdgeType) ==
395        canvas2->getClipBounds(&bounds2, SkCanvas::kBW_EdgeType),
396        testStep->assertMessage());
397    REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
398        testStep->assertMessage());
399    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() ==
400        canvas2->getDrawFilter(), testStep->assertMessage());
401    SkIRect deviceBounds1, deviceBounds2;
402    REPORTER_ASSERT_MESSAGE(reporter,
403        canvas1->getClipDeviceBounds(&deviceBounds1) ==
404        canvas2->getClipDeviceBounds(&deviceBounds2),
405        testStep->assertMessage());
406    REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2,
407        testStep->assertMessage());
408    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() ==
409        canvas2->getBounder(), testStep->assertMessage());
410    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() ==
411        canvas2->getTotalMatrix(), testStep->assertMessage());
412    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getClipType() ==
413        canvas2->getClipType(), testStep->assertMessage());
414    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() ==
415        canvas2->getTotalClip(), testStep->assertMessage());
416    REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClipStack() ==
417        canvas2->getTotalClipStack(), testStep->assertMessage());
418
419    // The following test code is commented out because the test fails when
420    // the canvas is an SkPictureRecord or SkDeferredCanvas
421    // Issue: http://code.google.com/p/skia/issues/detail?id=498
422    // Also, creating a LayerIter on an SkProxyCanvas crashes
423    // Issue: http://code.google.com/p/skia/issues/detail?id=499
424    /*
425    SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false);
426    SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false);
427    while (!layerIter1.done() && !layerIter2.done()) {
428        REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() ==
429            layerIter2.matrix(), testStep->assertMessage());
430        REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() ==
431            layerIter2.clip(), testStep->assertMessage());
432        REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() ==
433            layerIter2.paint(), testStep->assertMessage());
434        REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() ==
435            layerIter2.x(), testStep->assertMessage());
436        REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() ==
437            layerIter2.y(), testStep->assertMessage());
438        layerIter1.next();
439        layerIter2.next();
440    }
441    REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(),
442        testStep->assertMessage());
443    REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(),
444        testStep->assertMessage());
445    */
446}
447
448// The following class groups static functions that need to access
449// the privates members of SkPictureRecord
450class SkPictureTester {
451private:
452    static void AssertFlattenedObjectsEqual(
453        SkPictureRecord* referenceRecord,
454        SkPictureRecord* testRecord,
455        skiatest::Reporter* reporter,
456        CanvasTestStep* testStep) {
457
458        REPORTER_ASSERT_MESSAGE(reporter,
459            referenceRecord->fBitmaps.count() ==
460            testRecord->fBitmaps.count(), testStep->assertMessage());
461        for (int i = 0; i < referenceRecord->fBitmaps.count(); ++i) {
462            REPORTER_ASSERT_MESSAGE(reporter,
463                SkFlatData::Compare(referenceRecord->fBitmaps[i],
464                testRecord->fBitmaps[i]) == 0, testStep->assertMessage());
465        }
466        REPORTER_ASSERT_MESSAGE(reporter,
467            referenceRecord->fMatrices.count() ==
468            testRecord->fMatrices.count(), testStep->assertMessage());
469        for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) {
470            REPORTER_ASSERT_MESSAGE(reporter,
471                SkFlatData::Compare(referenceRecord->fMatrices[i],
472                testRecord->fMatrices[i]) == 0,
473                testStep->assertMessage());
474        }
475        REPORTER_ASSERT_MESSAGE(reporter,
476            referenceRecord->fPaints.count() ==
477            testRecord->fPaints.count(), testStep->assertMessage());
478        for (int i = 0; i < referenceRecord->fPaints.count(); ++i) {
479            REPORTER_ASSERT_MESSAGE(reporter,
480                SkFlatData::Compare(referenceRecord->fPaints[i],
481                testRecord->fPaints[i]) == 0, testStep->assertMessage());
482        }
483        REPORTER_ASSERT_MESSAGE(reporter,
484            referenceRecord->fRegions.count() ==
485            testRecord->fRegions.count(), testStep->assertMessage());
486        for (int i = 0; i < referenceRecord->fRegions.count(); ++i) {
487            REPORTER_ASSERT_MESSAGE(reporter,
488                SkFlatData::Compare(referenceRecord->fRegions[i],
489                testRecord->fRegions[i]) == 0, testStep->assertMessage());
490        }
491        REPORTER_ASSERT_MESSAGE(reporter,
492            !referenceRecord->fPathHeap ==
493            !testRecord->fPathHeap,
494            testStep->assertMessage());
495        // The following tests are commented out because they currently
496        // fail. Issue: http://code.google.com/p/skia/issues/detail?id=507
497        /*
498        if (referenceRecord->fPathHeap) {
499            REPORTER_ASSERT_MESSAGE(reporter,
500                referenceRecord->fPathHeap->count() ==
501                testRecord->fPathHeap->count(),
502                testStep->assertMessage());
503            for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) {
504                REPORTER_ASSERT_MESSAGE(reporter,
505                    (*referenceRecord->fPathHeap)[i] ==
506                    (*testRecord->fPathHeap)[i], testStep->assertMessage());
507            }
508        }
509        */
510
511    }
512
513public:
514
515    static void TestPictureSerializationRoundTrip(skiatest::Reporter* reporter,
516                                                  CanvasTestStep* testStep) {
517        testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
518        SkPicture referencePicture;
519        testStep->draw(referencePicture.beginRecording(kWidth, kHeight),
520            reporter);
521        SkPicture initialPicture;
522        testStep->draw(initialPicture.beginRecording(kWidth, kHeight),
523            reporter);
524        testStep->setAssertMessageFormat(kPictureReDrawAssertMessageFormat);
525        SkPicture roundTripPicture;
526        initialPicture.draw(roundTripPicture.beginRecording(kWidth, kHeight));
527
528        SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
529            referencePicture.getRecordingCanvas());
530        SkPictureRecord* roundTripRecord = static_cast<SkPictureRecord*>(
531            roundTripPicture.getRecordingCanvas());
532
533        testStep->setAssertMessageFormat(kPictureReDrawAssertMessageFormat);
534
535        // Verify that deserialization-serialization round trip conserves all
536        // data by comparing referenceRecord to roundTripRecord
537        REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fBitmapIndex ==
538            roundTripRecord->fBitmapIndex, testStep->assertMessage());
539        REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fMatrixIndex ==
540            roundTripRecord->fMatrixIndex, testStep->assertMessage());
541        REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fPaintIndex ==
542            roundTripRecord->fPaintIndex, testStep->assertMessage());
543        REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRegionIndex ==
544            roundTripRecord->fRegionIndex, testStep->assertMessage());
545        char referenceBuffer[kMaxPictureBufferSize];
546        SkMemoryWStream referenceStream(referenceBuffer,
547            kMaxPictureBufferSize);
548        referenceRecord->fWriter.writeToStream(&referenceStream);
549        char roundTripBuffer[kMaxPictureBufferSize];
550        SkMemoryWStream roundTripStream(roundTripBuffer,
551            kMaxPictureBufferSize);
552        roundTripRecord->fWriter.writeToStream(&roundTripStream);
553        REPORTER_ASSERT_MESSAGE(reporter,
554            roundTripStream.bytesWritten() == referenceStream.bytesWritten(),
555            testStep->assertMessage());
556        REPORTER_ASSERT_MESSAGE(reporter, 0 == memcmp(referenceBuffer,
557            roundTripBuffer, roundTripStream.bytesWritten()),
558            testStep->assertMessage());
559        REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRecordFlags ==
560            roundTripRecord->fRecordFlags, testStep->assertMessage());
561        REPORTER_ASSERT_MESSAGE(reporter,
562            referenceRecord->fRestoreOffsetStack ==
563            roundTripRecord->fRestoreOffsetStack,
564            testStep->assertMessage());
565        AssertFlattenedObjectsEqual(referenceRecord, roundTripRecord,
566            reporter, testStep);
567        AssertCanvasStatesEqual(reporter, referenceRecord, roundTripRecord,
568            testStep);
569    }
570
571    static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter,
572                                         CanvasTestStep* testStep) {
573        // Verify that when a test step is executed twice, no extra resources
574        // are flattened during the second execution
575        testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
576        SkPicture referencePicture;
577        SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth,
578            kHeight);
579        testStep->draw(referenceCanvas, reporter);
580        SkPicture testPicture;
581        SkCanvas* testCanvas = testPicture.beginRecording(kWidth,
582            kHeight);
583        testStep->draw(testCanvas, reporter);
584        testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat);
585        testStep->draw(testCanvas, reporter);
586
587        SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
588            referenceCanvas);
589        SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(
590            testCanvas);
591        testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat);
592        AssertFlattenedObjectsEqual(referenceRecord, testRecord,
593            reporter, testStep);
594    }
595};
596
597static void TestPictureStateConsistency(skiatest::Reporter* reporter,
598                                        CanvasTestStep* testStep,
599                                        const SkCanvas& referenceCanvas) {
600    // Verify that the recording canvas's state is consistent
601    // with that of a regular canvas
602    SkPicture testPicture;
603    SkCanvas* pictureCanvas = testPicture.beginRecording(kWidth, kHeight);
604    testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
605    testStep->draw(pictureCanvas, reporter);
606    testStep->setAssertMessageFormat(kPictureRecoringAssertMessageFormat);
607    AssertCanvasStatesEqual(reporter, pictureCanvas, &referenceCanvas,
608        testStep);
609
610    SkBitmap playbackStore;
611    createBitmap(&playbackStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
612    SkDevice playbackDevice(playbackStore);
613    SkCanvas playbackCanvas(&playbackDevice);
614    testPicture.draw(&playbackCanvas);
615    testStep->setAssertMessageFormat(kPicturePlaybackAssertMessageFormat);
616    AssertCanvasStatesEqual(reporter, &playbackCanvas, &referenceCanvas,
617        testStep);
618
619    // The following test code is commented out because SkPicture is not
620    // currently expected to preserve state when restarting recording.
621    /*
622    SkCanvas* pictureCanvas = testPicture.beginRecording(kWidth, kHeight);
623    testStep->setAssertMessageFormat(kPictureResumeAssertMessageFormat);
624    AssertCanvasStatesEqual(reporter, pictureCanvas, &referenceCanvas,
625        testStep);
626    */
627}
628
629static void TestDeferredCanvasStateConsistency(
630    skiatest::Reporter* reporter,
631    CanvasTestStep* testStep,
632    const SkCanvas& referenceCanvas) {
633
634    SkBitmap deferredStore;
635    createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
636    SkDevice deferredDevice(deferredStore);
637    SkDeferredCanvas deferredCanvas(&deferredDevice);
638    testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat);
639    testStep->draw(&deferredCanvas, reporter);
640    testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat);
641    AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
642        testStep);
643
644    // Verified that deferred canvas state is not affected by flushing
645    // pending draw operations
646
647    // The following test code is commented out because it currently fails.
648    // Issue: http://code.google.com/p/skia/issues/detail?id=496
649    /*
650    deferredCanvas.flush();
651    testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat);
652    AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
653        testStep);
654    */
655}
656
657static void TestProxyCanvasStateConsistency(
658    skiatest::Reporter* reporter,
659    CanvasTestStep* testStep,
660    const SkCanvas& referenceCanvas) {
661
662    SkBitmap indirectStore;
663    createBitmap(&indirectStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
664    SkDevice indirectDevice(indirectStore);
665    SkCanvas indirectCanvas(&indirectDevice);
666    SkProxyCanvas proxyCanvas(&indirectCanvas);
667    testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat);
668    testStep->draw(&proxyCanvas, reporter);
669    // Verify that the SkProxyCanvas reports consitent state
670    testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat);
671    AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas,
672        testStep);
673    // Verify that the indirect canvas reports consitent state
674    testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat);
675    AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas,
676        testStep);
677}
678
679static void TestNWayCanvasStateConsistency(
680    skiatest::Reporter* reporter,
681    CanvasTestStep* testStep,
682    const SkCanvas& referenceCanvas) {
683
684    SkBitmap indirectStore1;
685    createBitmap(&indirectStore1, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
686    SkDevice indirectDevice1(indirectStore1);
687    SkCanvas indirectCanvas1(&indirectDevice1);
688
689    SkBitmap indirectStore2;
690    createBitmap(&indirectStore2, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
691    SkDevice indirectDevice2(indirectStore2);
692    SkCanvas indirectCanvas2(&indirectDevice2);
693
694    SkNWayCanvas nWayCanvas;
695    nWayCanvas.addCanvas(&indirectCanvas1);
696    nWayCanvas.addCanvas(&indirectCanvas2);
697
698    testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat);
699    testStep->draw(&nWayCanvas, reporter);
700    // Verify that the SkProxyCanvas reports consitent state
701    testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat);
702    AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas,
703        testStep);
704    // Verify that the indirect canvases report consitent state
705    testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat);
706    AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas,
707        testStep);
708    testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat);
709    AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas,
710        testStep);
711}
712
713/*
714 * This sub-test verifies that the test step passes when executed
715 * with SkCanvas and with classes derrived from SkCanvas. It also verifies
716 * that the all canvas derivatives report the same state as an SkCanvas
717 * after having executed the test step.
718 */
719static void TestOverrideStateConsistency(skiatest::Reporter* reporter,
720                                         CanvasTestStep* testStep) {
721    SkBitmap referenceStore;
722    createBitmap(&referenceStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
723    SkDevice referenceDevice(referenceStore);
724    SkCanvas referenceCanvas(&referenceDevice);
725    testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat);
726    testStep->draw(&referenceCanvas, reporter);
727
728    TestPictureStateConsistency(reporter, testStep, referenceCanvas);
729    TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas);
730
731    // The following test code is commented out because SkProxyCanvas is
732    // missing a lot of virtual overrides on get* methods, which are used
733    // to verify canvas state.
734    // Issue: http://code.google.com/p/skia/issues/detail?id=500
735
736    //TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas);
737
738    // The following test code is commented out because SkNWayCanvas does not
739    // report correct clipping and device bounds information
740    // Issue: http://code.google.com/p/skia/issues/detail?id=501
741
742    //TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas);
743}
744
745static void TestCanvas(skiatest::Reporter* reporter) {
746    // Init global here because bitmap pixels cannot be alocated during
747    // static initialization
748    kTestBitmap = testBitmap();
749
750    for (int testStep = 0; testStep < testStepArray().count(); testStep++) {
751        TestOverrideStateConsistency(reporter, testStepArray()[testStep]);
752        SkPictureTester::TestPictureSerializationRoundTrip(reporter,
753            testStepArray()[testStep]);
754        SkPictureTester::TestPictureFlattenedObjectReuse(reporter,
755            testStepArray()[testStep]);
756    }
757}
758
759#include "TestClassDef.h"
760DEFINE_TESTCLASS("Canvas", TestCanvasClass, TestCanvas)
761