skia2/tests/CanvasTest.cpp
caryclark@google.com 42639cddc3 fix warnings on Mac in tests
Fix these class of warnings:
- unused functions
- unused locals
- sign mismatch
- missing function prototypes
- missing newline at end of file
- 64 to 32 bit truncation

The changes prefer to link in dead code in the debug build
with 'if (false)' than to comment it out, but trivial cases
are commented out or sometimes deleted if it appears to be
a copy/paste error.
Review URL: https://codereview.appspot.com/6301045

git-svn-id: http://skia.googlecode.com/svn/trunk@4175 2bbb7eff-a529-9590-31e7-b0007b416f81
2012-06-06 12:03:39 +00:00

848 lines
36 KiB
C++

/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Description:
* This test defines a series of elementatry test steps that perform
* a single or a small group of canvas API calls. Each test step is
* used in several test cases that verify that different types of SkCanvas
* flavors and derivatives pass it and yield consistent behavior. The
* test cases analyse results that are queryable through the API. They do
* not look at rendering results.
*
* Adding test stepss:
* The general pattern for creating a new test step is to write a test
* function of the form:
*
* static void MyTestStepFunction(SkCanvas* canvas,
* skiatest::Reporter* reporter,
* CanvasTestStep* testStep)
* {
* canvas->someCanvasAPImethod();
* (...)
* REPORTER_ASSERT_MESSAGE(reporter, (...), \
* testStep->assertMessage());
* }
*
* The definition of the test step function should be followed by an
* invocation of the TEST_STEP macro, which generates a class and
* instance for the test step:
*
* TEST_STEP(MyTestStep, MyTestStepFunction)
*
* There are also short hand macros for defining simple test steps
* in a single line of code. A simple test step is a one that is made
* of a single canvas API call.
*
* SIMPLE_TEST_STEP(MytestStep, someCanvasAPIMethod());
*
* There is another macro called SIMPLE_TEST_STEP_WITH_ASSERT that
* works the same way as SIMPLE_TEST_STEP, and additionally verifies
* that the invoked method returns a non-zero value.
*/
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDeferredCanvas.h"
#include "SkDevice.h"
#include "SkMatrix.h"
#include "SkNWayCanvas.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkPictureRecord.h"
#include "SkProxyCanvas.h"
#include "SkRect.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkStream.h"
#include "SkTDArray.h"
#include "Test.h"
class Canvas2CanvasClipVisitor : public SkCanvas::ClipVisitor {
public:
Canvas2CanvasClipVisitor(SkCanvas* target) : fTarget(target) {}
virtual void clipRect(const SkRect& r, SkRegion::Op op, bool aa) {
fTarget->clipRect(r, op, aa);
}
virtual void clipPath(const SkPath& p, SkRegion::Op op, bool aa) {
fTarget->clipPath(p, op, aa);
}
private:
SkCanvas* fTarget;
};
static void test_clipVisitor(skiatest::Reporter* reporter, SkCanvas* canvas) {
SkISize size = canvas->getDeviceSize();
SkBitmap bm;
bm.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
SkCanvas c(bm);
Canvas2CanvasClipVisitor visitor(&c);
canvas->replayClips(&visitor);
REPORTER_ASSERT(reporter, c.getTotalClip() == canvas->getTotalClip());
}
static const int kWidth = 2;
static const int kHeight = 2;
// Maximum stream length for picture serialization
static const size_t kMaxPictureBufferSize = 1024;
// Format strings that describe the test context. The %s token is where
// the name of the test step is inserted. The context is required for
// disambiguating the error in the case of failures that are reported in
// functions that are called multiple times in different contexts (test
// cases and test steps).
static const char* const kDefaultAssertMessageFormat = "%s";
static const char* const kCanvasDrawAssertMessageFormat =
"Drawing test step %s with SkCanvas";
static const char* const kPictureDrawAssertMessageFormat =
"Drawing test step %s with SkPicture";
static const char* const kPictureSecondDrawAssertMessageFormat =
"Duplicate draw of test step %s with SkPicture";
static const char* const kPictureReDrawAssertMessageFormat =
"Playing back test step %s from an SkPicture to another SkPicture";
static const char* const kDeferredDrawAssertMessageFormat =
"Drawing test step %s with SkDeferredCanvas";
static const char* const kProxyDrawAssertMessageFormat =
"Drawing test step %s with SkProxyCanvas";
static const char* const kNWayDrawAssertMessageFormat =
"Drawing test step %s with SkNWayCanvas";
static const char* const kRoundTripAssertMessageFormat =
"test step %s, SkPicture consistency after round trip";
static const char* const kPictureRecoringAssertMessageFormat =
"test step %s, SkPicture state consistency after recording";
static const char* const kPicturePlaybackAssertMessageFormat =
"test step %s, SkPicture state consistency in playback canvas";
static const char* const kDeferredPreFlushAssertMessageFormat =
"test step %s, SkDeferredCanvas state consistency before flush";
static const char* const kDeferredPostFlushAssertMessageFormat =
"test step %s, SkDeferredCanvas state consistency after flush";
static const char* const kPictureResourceReuseMessageFormat =
"test step %s, SkPicture duplicate flattened object test";
static const char* const kProxyStateAssertMessageFormat =
"test step %s, SkProxyCanvas state consistency";
static const char* const kProxyIndirectStateAssertMessageFormat =
"test step %s, SkProxyCanvas indirect canvas state consistency";
static const char* const kNWayStateAssertMessageFormat =
"test step %s, SkNWayCanvas state consistency";
static const char* const kNWayIndirect1StateAssertMessageFormat =
"test step %s, SkNWayCanvas indirect canvas 1 state consistency";
static const char* const kNWayIndirect2StateAssertMessageFormat =
"test step %s, SkNWayCanvas indirect canvas 2 state consistency";
static void createBitmap(SkBitmap* bm, SkBitmap::Config config, SkColor color) {
bm->setConfig(config, kWidth, kHeight);
bm->allocPixels();
bm->eraseColor(color);
}
class CanvasTestStep;
static SkTDArray<CanvasTestStep*>& testStepArray() {
static SkTDArray<CanvasTestStep*> theTests;
return theTests;
}
class CanvasTestStep {
public:
CanvasTestStep() {
*testStepArray().append() = this;
fAssertMessageFormat = kDefaultAssertMessageFormat;
}
virtual ~CanvasTestStep() { }
virtual void draw(SkCanvas*, skiatest::Reporter*) = 0;
virtual const char* name() const = 0;
const char* assertMessage() {
fAssertMessage.printf(fAssertMessageFormat, name());
return fAssertMessage.c_str();
}
void setAssertMessageFormat(const char* format) {
fAssertMessageFormat = format;
}
private:
SkString fAssertMessage;
const char* fAssertMessageFormat;
};
///////////////////////////////////////////////////////////////////////////////
// Constants used by test steps
const SkRect kTestRect =
SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(2), SkIntToScalar(1));
static SkMatrix testMatrix() {
SkMatrix matrix;
matrix.reset();
matrix.setScale(SkIntToScalar(2), SkIntToScalar(3));
return matrix;
}
const SkMatrix kTestMatrix = testMatrix();
static SkPath testPath() {
SkPath path;
path.addRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(2), SkIntToScalar(1)));
return path;
}
const SkPath kTestPath = testPath();
static SkRegion testRegion() {
SkRegion region;
SkIRect rect = SkIRect::MakeXYWH(0, 0, 2, 1);
region.setRect(rect);
return region;
}
const SkIRect kTestIRect = SkIRect::MakeXYWH(0, 0, 2, 1);
const SkRegion kTestRegion = testRegion();
const SkColor kTestColor = 0x01020304;
const SkPaint kTestPaint;
const SkPoint kTestPoints[3] = {
{SkIntToScalar(0), SkIntToScalar(0)},
{SkIntToScalar(2), SkIntToScalar(1)},
{SkIntToScalar(0), SkIntToScalar(2)}
};
const size_t kTestPointCount = 3;
static SkBitmap testBitmap() {
SkBitmap bitmap;
createBitmap(&bitmap, SkBitmap::kARGB_8888_Config, 0x05060708);
return bitmap;
}
SkBitmap kTestBitmap; // cannot be created during static init
SkString kTestText("Hello World");
SkPoint kTestPoints2[] = {
{ SkIntToScalar(0), SkIntToScalar(1) },
{ SkIntToScalar(1), SkIntToScalar(1) },
{ SkIntToScalar(2), SkIntToScalar(1) },
{ SkIntToScalar(3), SkIntToScalar(1) },
{ SkIntToScalar(4), SkIntToScalar(1) },
{ SkIntToScalar(5), SkIntToScalar(1) },
{ SkIntToScalar(6), SkIntToScalar(1) },
{ SkIntToScalar(7), SkIntToScalar(1) },
{ SkIntToScalar(8), SkIntToScalar(1) },
{ SkIntToScalar(9), SkIntToScalar(1) },
{ SkIntToScalar(10), SkIntToScalar(1) },
};
///////////////////////////////////////////////////////////////////////////////
// Macros for defining test steps
#define TEST_STEP(NAME, FUNCTION) \
class NAME##_TestStep : public CanvasTestStep{ \
public: \
virtual void draw(SkCanvas* canvas, skiatest::Reporter* reporter) { \
FUNCTION (canvas, reporter, this); \
} \
virtual const char* name() const {return #NAME ;} \
}; \
static NAME##_TestStep NAME##_TestStepInstance;
#define SIMPLE_TEST_STEP(NAME, CALL) \
static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter*, \
CanvasTestStep*) { \
canvas-> CALL ; \
} \
TEST_STEP(NAME, NAME##TestStep )
#define SIMPLE_TEST_STEP_WITH_ASSERT(NAME, CALL) \
static void NAME##TestStep(SkCanvas* canvas, skiatest::Reporter* reporter, \
CanvasTestStep* testStep) { \
REPORTER_ASSERT_MESSAGE(reporter, canvas-> CALL , \
testStep->assertMessage()); \
} \
TEST_STEP(NAME, NAME##TestStep )
///////////////////////////////////////////////////////////////////////////////
// Basic test steps for most virtual methods in SkCanvas that draw or affect
// the state of the canvas.
SIMPLE_TEST_STEP(SaveMatrix, save(SkCanvas::kMatrix_SaveFlag));
SIMPLE_TEST_STEP(SaveClip, save(SkCanvas::kClip_SaveFlag));
SIMPLE_TEST_STEP(SaveMatrixClip, save(SkCanvas::kMatrixClip_SaveFlag));
SIMPLE_TEST_STEP(SaveLayer, saveLayer(NULL, NULL));
SIMPLE_TEST_STEP(BoundedSaveLayer, saveLayer(&kTestRect, NULL));
SIMPLE_TEST_STEP(PaintSaveLayer, saveLayer(NULL, &kTestPaint));
SIMPLE_TEST_STEP_WITH_ASSERT(Translate,
translate(SkIntToScalar(1), SkIntToScalar(2)));
SIMPLE_TEST_STEP_WITH_ASSERT(Scale,
scale(SkIntToScalar(1), SkIntToScalar(2)));
SIMPLE_TEST_STEP_WITH_ASSERT(Rotate, rotate(SkIntToScalar(1)));
SIMPLE_TEST_STEP_WITH_ASSERT(Skew,
skew(SkIntToScalar(1), SkIntToScalar(2)));
SIMPLE_TEST_STEP_WITH_ASSERT(Concat, concat(kTestMatrix));
SIMPLE_TEST_STEP(SetMatrix, setMatrix(kTestMatrix));
SIMPLE_TEST_STEP_WITH_ASSERT(ClipRect, clipRect(kTestRect));
SIMPLE_TEST_STEP_WITH_ASSERT(ClipPath, clipPath(kTestPath));
SIMPLE_TEST_STEP_WITH_ASSERT(ClipRegion,
clipRegion(kTestRegion, SkRegion::kReplace_Op));
SIMPLE_TEST_STEP(Clear, clear(kTestColor));
SIMPLE_TEST_STEP(DrawPaint, drawPaint(kTestPaint));
SIMPLE_TEST_STEP(DrawPointsPoints, drawPoints(SkCanvas::kPoints_PointMode,
kTestPointCount, kTestPoints, kTestPaint));
SIMPLE_TEST_STEP(DrawPointsLiness, drawPoints(SkCanvas::kLines_PointMode,
kTestPointCount, kTestPoints, kTestPaint));
SIMPLE_TEST_STEP(DrawPointsPolygon, drawPoints(SkCanvas::kPolygon_PointMode,
kTestPointCount, kTestPoints, kTestPaint));
SIMPLE_TEST_STEP(DrawRect, drawRect(kTestRect, kTestPaint));
SIMPLE_TEST_STEP(DrawPath, drawPath(kTestPath, kTestPaint));
SIMPLE_TEST_STEP(DrawBitmap, drawBitmap(kTestBitmap, 0, 0));
SIMPLE_TEST_STEP(DrawBitmapPaint, drawBitmap(kTestBitmap, 0, 0, &kTestPaint));
SIMPLE_TEST_STEP(DrawBitmapRect, drawBitmapRect(kTestBitmap, NULL, kTestRect,
NULL));
SIMPLE_TEST_STEP(DrawBitmapRectSrcRect, drawBitmapRect(kTestBitmap,
&kTestIRect, kTestRect, NULL));
SIMPLE_TEST_STEP(DrawBitmapRectPaint, drawBitmapRect(kTestBitmap, NULL,
kTestRect, &kTestPaint));
SIMPLE_TEST_STEP(DrawBitmapMatrix, drawBitmapMatrix(kTestBitmap, kTestMatrix,
NULL));
SIMPLE_TEST_STEP(DrawBitmapMatrixPaint, drawBitmapMatrix(kTestBitmap,
kTestMatrix, &kTestPaint));
SIMPLE_TEST_STEP(DrawBitmapNine, drawBitmapNine(kTestBitmap, kTestIRect,
kTestRect, NULL));
SIMPLE_TEST_STEP(DrawBitmapNinePaint, drawBitmapNine(kTestBitmap, kTestIRect,
kTestRect, &kTestPaint));
SIMPLE_TEST_STEP(DrawSprite, drawSprite(kTestBitmap, 0, 0, NULL));
SIMPLE_TEST_STEP(DrawSpritePaint, drawSprite(kTestBitmap, 0, 0, &kTestPaint));
SIMPLE_TEST_STEP(DrawText, drawText(kTestText.c_str(), kTestText.size(),
0, 1, kTestPaint));
SIMPLE_TEST_STEP(DrawPosText, drawPosText(kTestText.c_str(),
kTestText.size(), kTestPoints2, kTestPaint));
SIMPLE_TEST_STEP(DrawTextOnPath, drawTextOnPath(kTestText.c_str(),
kTestText.size(), kTestPath, NULL, kTestPaint));
SIMPLE_TEST_STEP(DrawTextOnPathMatrix, drawTextOnPath(kTestText.c_str(),
kTestText.size(), kTestPath, &kTestMatrix, kTestPaint));
SIMPLE_TEST_STEP(SetExternalMatrix, setExternalMatrix(&kTestMatrix));
SIMPLE_TEST_STEP(DrawData, drawData(kTestText.c_str(), kTestText.size()));
///////////////////////////////////////////////////////////////////////////////
// Complex test steps
// exercise fix for http://code.google.com/p/skia/issues/detail?id=560
// ('SkPathStroker::lineTo() fails for line with length SK_ScalarNearlyZero')
static void DrawNearlyZeroLengthPathTestStep(SkCanvas* canvas,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
SkPaint paint;
paint.setStrokeWidth(SkIntToScalar(1));
paint.setStyle(SkPaint::kStroke_Style);
SkPath path;
SkPoint pt1 = { 0, 0 };
SkPoint pt2 = { 0, SK_ScalarNearlyZero };
SkPoint pt3 = { SkIntToScalar(1), 0 };
SkPoint pt4 = { SkIntToScalar(1), SK_ScalarNearlyZero/2 };
path.moveTo(pt1);
path.lineTo(pt2);
path.lineTo(pt3);
path.lineTo(pt4);
canvas->drawPath(path, paint);
}
TEST_STEP(DrawNearlyZeroLengthPath, DrawNearlyZeroLengthPathTestStep);
static void DrawVerticesShaderTestStep(SkCanvas* canvas,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
SkPoint pts[4];
pts[0].set(0, 0);
pts[1].set(SkIntToScalar(kWidth), 0);
pts[2].set(SkIntToScalar(kWidth), SkIntToScalar(kHeight));
pts[3].set(0, SkIntToScalar(kHeight));
SkPaint paint;
SkShader* shader = SkShader::CreateBitmapShader(kTestBitmap,
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
paint.setShader(shader)->unref();
canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, 4, pts, pts,
NULL, NULL, NULL, 0, paint);
}
TEST_STEP(DrawVerticesShader, DrawVerticesShaderTestStep);
static void DrawPictureTestStep(SkCanvas* canvas,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
SkPicture* testPicture = SkNEW_ARGS(SkPicture, ());
SkAutoUnref aup(testPicture);
SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight);
testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
testCanvas->clipRect(kTestRect);
testCanvas->drawRect(kTestRect, kTestPaint);
canvas->drawPicture(*testPicture);
}
TEST_STEP(DrawPicture, DrawPictureTestStep);
static void SaveRestoreTestStep(SkCanvas* canvas,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
testStep->assertMessage());
size_t n = canvas->save();
REPORTER_ASSERT_MESSAGE(reporter, 1 == n, testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, 2 == canvas->getSaveCount(),
testStep->assertMessage());
canvas->save();
canvas->save();
REPORTER_ASSERT_MESSAGE(reporter, 4 == canvas->getSaveCount(),
testStep->assertMessage());
canvas->restoreToCount(2);
REPORTER_ASSERT_MESSAGE(reporter, 2 == canvas->getSaveCount(),
testStep->assertMessage());
// should this pin to 1, or be a no-op, or crash?
canvas->restoreToCount(0);
REPORTER_ASSERT_MESSAGE(reporter, 1 == canvas->getSaveCount(),
testStep->assertMessage());
}
TEST_STEP(SaveRestore, SaveRestoreTestStep);
static void DrawLayerTestStep(SkCanvas* canvas,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
testStep->assertMessage());
canvas->save();
REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
testStep->assertMessage());
const SkRect* bounds = NULL; // null means include entire bounds
const SkPaint* paint = NULL;
canvas->saveLayer(bounds, paint);
REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
testStep->assertMessage());
canvas->restore();
REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
testStep->assertMessage());
canvas->saveLayer(bounds, paint);
canvas->saveLayer(bounds, paint);
REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
testStep->assertMessage());
canvas->restore();
REPORTER_ASSERT_MESSAGE(reporter, canvas->isDrawingToLayer(),
testStep->assertMessage());
canvas->restore();
// now layer count should be 0
REPORTER_ASSERT_MESSAGE(reporter, !canvas->isDrawingToLayer(),
testStep->assertMessage());
}
TEST_STEP(DrawLayer, DrawLayerTestStep);
static void AssertCanvasStatesEqual(skiatest::Reporter* reporter,
const SkCanvas* canvas1,
const SkCanvas* canvas2,
CanvasTestStep* testStep) {
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDeviceSize() ==
canvas2->getDeviceSize(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getSaveCount() ==
canvas2->getSaveCount(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->isDrawingToLayer() ==
canvas2->isDrawingToLayer(), testStep->assertMessage());
SkRect bounds1, bounds2;
REPORTER_ASSERT_MESSAGE(reporter,
canvas1->getClipBounds(&bounds1, SkCanvas::kAA_EdgeType) ==
canvas2->getClipBounds(&bounds2, SkCanvas::kAA_EdgeType),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter,
canvas1->getClipBounds(&bounds1, SkCanvas::kBW_EdgeType) ==
canvas2->getClipBounds(&bounds2, SkCanvas::kBW_EdgeType),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, bounds1 == bounds2,
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getDrawFilter() ==
canvas2->getDrawFilter(), testStep->assertMessage());
SkIRect deviceBounds1, deviceBounds2;
REPORTER_ASSERT_MESSAGE(reporter,
canvas1->getClipDeviceBounds(&deviceBounds1) ==
canvas2->getClipDeviceBounds(&deviceBounds2),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, deviceBounds1 == deviceBounds2,
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getBounder() ==
canvas2->getBounder(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalMatrix() ==
canvas2->getTotalMatrix(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getClipType() ==
canvas2->getClipType(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, canvas1->getTotalClip() ==
canvas2->getTotalClip(), testStep->assertMessage());
// The following test code is commented out because the test fails when
// the canvas is an SkPictureRecord or SkDeferredCanvas
// Issue: http://code.google.com/p/skia/issues/detail?id=498
// Also, creating a LayerIter on an SkProxyCanvas crashes
// Issue: http://code.google.com/p/skia/issues/detail?id=499
/*
SkCanvas::LayerIter layerIter1(const_cast<SkCanvas*>(canvas1), false);
SkCanvas::LayerIter layerIter2(const_cast<SkCanvas*>(canvas2), false);
while (!layerIter1.done() && !layerIter2.done()) {
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.matrix() ==
layerIter2.matrix(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.clip() ==
layerIter2.clip(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.paint() ==
layerIter2.paint(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.x() ==
layerIter2.x(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.y() ==
layerIter2.y(), testStep->assertMessage());
layerIter1.next();
layerIter2.next();
}
REPORTER_ASSERT_MESSAGE(reporter, layerIter1.done(),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, layerIter2.done(),
testStep->assertMessage());
*/
}
// The following class groups static functions that need to access
// the privates members of SkPictureRecord
class SkPictureTester {
private:
static void AssertFlattenedObjectsEqual(
SkPictureRecord* referenceRecord,
SkPictureRecord* testRecord,
skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fBitmaps.count() ==
testRecord->fBitmaps.count(), testStep->assertMessage());
for (int i = 0; i < referenceRecord->fBitmaps.count(); ++i) {
REPORTER_ASSERT_MESSAGE(reporter,
SkFlatData::Compare(referenceRecord->fBitmaps[i],
testRecord->fBitmaps[i]) == 0, testStep->assertMessage());
}
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fMatrices.count() ==
testRecord->fMatrices.count(), testStep->assertMessage());
for (int i = 0; i < referenceRecord->fMatrices.count(); ++i) {
REPORTER_ASSERT_MESSAGE(reporter,
SkFlatData::Compare(referenceRecord->fMatrices[i],
testRecord->fMatrices[i]) == 0,
testStep->assertMessage());
}
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fPaints.count() ==
testRecord->fPaints.count(), testStep->assertMessage());
for (int i = 0; i < referenceRecord->fPaints.count(); ++i) {
REPORTER_ASSERT_MESSAGE(reporter,
SkFlatData::Compare(referenceRecord->fPaints[i],
testRecord->fPaints[i]) == 0, testStep->assertMessage());
}
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fRegions.count() ==
testRecord->fRegions.count(), testStep->assertMessage());
for (int i = 0; i < referenceRecord->fRegions.count(); ++i) {
REPORTER_ASSERT_MESSAGE(reporter,
SkFlatData::Compare(referenceRecord->fRegions[i],
testRecord->fRegions[i]) == 0, testStep->assertMessage());
}
REPORTER_ASSERT_MESSAGE(reporter,
!referenceRecord->fPathHeap ==
!testRecord->fPathHeap,
testStep->assertMessage());
// The following tests are commented out because they currently
// fail. Issue: http://code.google.com/p/skia/issues/detail?id=507
/*
if (referenceRecord->fPathHeap) {
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fPathHeap->count() ==
testRecord->fPathHeap->count(),
testStep->assertMessage());
for (int i = 0; i < referenceRecord->fPathHeap->count(); ++i) {
REPORTER_ASSERT_MESSAGE(reporter,
(*referenceRecord->fPathHeap)[i] ==
(*testRecord->fPathHeap)[i], testStep->assertMessage());
}
}
*/
}
public:
static void TestPictureSerializationRoundTrip(skiatest::Reporter* reporter,
CanvasTestStep* testStep,
uint32_t recordFlags) {
testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
SkPicture referencePicture;
testStep->draw(referencePicture.beginRecording(kWidth, kHeight,
recordFlags), reporter);
SkPicture initialPicture;
testStep->draw(initialPicture.beginRecording(kWidth, kHeight,
recordFlags), reporter);
testStep->setAssertMessageFormat(kPictureReDrawAssertMessageFormat);
SkPicture roundTripPicture;
initialPicture.draw(roundTripPicture.beginRecording(kWidth, kHeight,
recordFlags));
SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
referencePicture.getRecordingCanvas());
SkPictureRecord* roundTripRecord = static_cast<SkPictureRecord*>(
roundTripPicture.getRecordingCanvas());
testStep->setAssertMessageFormat(kPictureReDrawAssertMessageFormat);
// Verify that deserialization-serialization round trip conserves all
// data by comparing referenceRecord to roundTripRecord
REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fBitmaps.count() ==
roundTripRecord->fBitmaps.count(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fMatrices.count() ==
roundTripRecord->fMatrices.count(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fPaints.count() ==
roundTripRecord->fPaints.count(), testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRegions.count() ==
roundTripRecord->fRegions.count(), testStep->assertMessage());
char referenceBuffer[kMaxPictureBufferSize];
SkMemoryWStream referenceStream(referenceBuffer,
kMaxPictureBufferSize);
referenceRecord->fWriter.writeToStream(&referenceStream);
char roundTripBuffer[kMaxPictureBufferSize];
SkMemoryWStream roundTripStream(roundTripBuffer,
kMaxPictureBufferSize);
roundTripRecord->fWriter.writeToStream(&roundTripStream);
REPORTER_ASSERT_MESSAGE(reporter,
roundTripStream.bytesWritten() == referenceStream.bytesWritten(),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, 0 == memcmp(referenceBuffer,
roundTripBuffer, roundTripStream.bytesWritten()),
testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter, referenceRecord->fRecordFlags ==
roundTripRecord->fRecordFlags, testStep->assertMessage());
REPORTER_ASSERT_MESSAGE(reporter,
referenceRecord->fRestoreOffsetStack ==
roundTripRecord->fRestoreOffsetStack,
testStep->assertMessage());
AssertFlattenedObjectsEqual(referenceRecord, roundTripRecord,
reporter, testStep);
AssertCanvasStatesEqual(reporter, referenceRecord, roundTripRecord,
testStep);
}
static void TestPictureFlattenedObjectReuse(skiatest::Reporter* reporter,
CanvasTestStep* testStep,
uint32_t recordFlags) {
// Verify that when a test step is executed twice, no extra resources
// are flattened during the second execution
testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
SkPicture referencePicture;
SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth,
kHeight, recordFlags);
testStep->draw(referenceCanvas, reporter);
SkPicture testPicture;
SkCanvas* testCanvas = testPicture.beginRecording(kWidth,
kHeight, recordFlags);
testStep->draw(testCanvas, reporter);
testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat);
testStep->draw(testCanvas, reporter);
SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
referenceCanvas);
SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(
testCanvas);
testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat);
AssertFlattenedObjectsEqual(referenceRecord, testRecord,
reporter, testStep);
}
};
static void TestPictureStateConsistency(skiatest::Reporter* reporter,
CanvasTestStep* testStep,
const SkCanvas& referenceCanvas,
uint32_t recordFlags) {
// Verify that the recording canvas's state is consistent
// with that of a regular canvas
SkPicture testPicture;
SkCanvas* pictureCanvas = testPicture.beginRecording(kWidth, kHeight,
recordFlags);
testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
testStep->draw(pictureCanvas, reporter);
testStep->setAssertMessageFormat(kPictureRecoringAssertMessageFormat);
AssertCanvasStatesEqual(reporter, pictureCanvas, &referenceCanvas,
testStep);
SkBitmap playbackStore;
createBitmap(&playbackStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice playbackDevice(playbackStore);
SkCanvas playbackCanvas(&playbackDevice);
testPicture.draw(&playbackCanvas);
testStep->setAssertMessageFormat(kPicturePlaybackAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &playbackCanvas, &referenceCanvas,
testStep);
// The following test code is commented out because SkPicture is not
// currently expected to preserve state when restarting recording.
/*
SkCanvas* pictureCanvas = testPicture.beginRecording(kWidth, kHeight,
recordFlags);
testStep->setAssertMessageFormat(kPictureResumeAssertMessageFormat);
AssertCanvasStatesEqual(reporter, pictureCanvas, &referenceCanvas,
testStep);
*/
}
static void TestDeferredCanvasStateConsistency(
skiatest::Reporter* reporter,
CanvasTestStep* testStep,
const SkCanvas& referenceCanvas) {
SkBitmap deferredStore;
createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice deferredDevice(deferredStore);
SkDeferredCanvas deferredCanvas(&deferredDevice);
testStep->setAssertMessageFormat(kDeferredDrawAssertMessageFormat);
testStep->draw(&deferredCanvas, reporter);
testStep->setAssertMessageFormat(kDeferredPreFlushAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
testStep);
// Verified that deferred canvas state is not affected by flushing
// pending draw operations
// The following test code is commented out because it currently fails.
// Issue: http://code.google.com/p/skia/issues/detail?id=496
/*
deferredCanvas.flush();
testStep->setAssertMessageFormat(kDeferredPostFlushAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
testStep);
*/
}
// unused
static void TestProxyCanvasStateConsistency(
skiatest::Reporter* reporter,
CanvasTestStep* testStep,
const SkCanvas& referenceCanvas) {
SkBitmap indirectStore;
createBitmap(&indirectStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice indirectDevice(indirectStore);
SkCanvas indirectCanvas(&indirectDevice);
SkProxyCanvas proxyCanvas(&indirectCanvas);
testStep->setAssertMessageFormat(kProxyDrawAssertMessageFormat);
testStep->draw(&proxyCanvas, reporter);
// Verify that the SkProxyCanvas reports consitent state
testStep->setAssertMessageFormat(kProxyStateAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &proxyCanvas, &referenceCanvas,
testStep);
// Verify that the indirect canvas reports consitent state
testStep->setAssertMessageFormat(kProxyIndirectStateAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &indirectCanvas, &referenceCanvas,
testStep);
}
// unused
static void TestNWayCanvasStateConsistency(
skiatest::Reporter* reporter,
CanvasTestStep* testStep,
const SkCanvas& referenceCanvas) {
SkBitmap indirectStore1;
createBitmap(&indirectStore1, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice indirectDevice1(indirectStore1);
SkCanvas indirectCanvas1(&indirectDevice1);
SkBitmap indirectStore2;
createBitmap(&indirectStore2, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice indirectDevice2(indirectStore2);
SkCanvas indirectCanvas2(&indirectDevice2);
SkISize canvasSize = referenceCanvas.getDeviceSize();
SkNWayCanvas nWayCanvas(canvasSize.width(), canvasSize.height());
nWayCanvas.addCanvas(&indirectCanvas1);
nWayCanvas.addCanvas(&indirectCanvas2);
testStep->setAssertMessageFormat(kNWayDrawAssertMessageFormat);
testStep->draw(&nWayCanvas, reporter);
// Verify that the SkProxyCanvas reports consitent state
testStep->setAssertMessageFormat(kNWayStateAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &nWayCanvas, &referenceCanvas,
testStep);
// Verify that the indirect canvases report consitent state
testStep->setAssertMessageFormat(kNWayIndirect1StateAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &indirectCanvas1, &referenceCanvas,
testStep);
testStep->setAssertMessageFormat(kNWayIndirect2StateAssertMessageFormat);
AssertCanvasStatesEqual(reporter, &indirectCanvas2, &referenceCanvas,
testStep);
}
/*
* This sub-test verifies that the test step passes when executed
* with SkCanvas and with classes derrived from SkCanvas. It also verifies
* that the all canvas derivatives report the same state as an SkCanvas
* after having executed the test step.
*/
static void TestOverrideStateConsistency(skiatest::Reporter* reporter,
CanvasTestStep* testStep) {
SkBitmap referenceStore;
createBitmap(&referenceStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
SkDevice referenceDevice(referenceStore);
SkCanvas referenceCanvas(&referenceDevice);
testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat);
testStep->draw(&referenceCanvas, reporter);
TestPictureStateConsistency(reporter, testStep, referenceCanvas, 0);
TestPictureStateConsistency(reporter, testStep, referenceCanvas,
SkPicture::kFlattenMutableNonTexturePixelRefs_RecordingFlag);
TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas);
// The following test code is disabled because SkProxyCanvas is
// missing a lot of virtual overrides on get* methods, which are used
// to verify canvas state.
// Issue: http://code.google.com/p/skia/issues/detail?id=500
if (false) { // avoid bit rot, suppress warning
TestProxyCanvasStateConsistency(reporter, testStep, referenceCanvas);
}
// The following test code is disabled because SkNWayCanvas does not
// report correct clipping and device bounds information
// Issue: http://code.google.com/p/skia/issues/detail?id=501
if (false) { // avoid bit rot, suppress warning
TestNWayCanvasStateConsistency(reporter, testStep, referenceCanvas);
}
if (false) { // avoid bit rot, suppress warning
test_clipVisitor(reporter, &referenceCanvas);
}
}
static void TestCanvas(skiatest::Reporter* reporter) {
// Init global here because bitmap pixels cannot be alocated during
// static initialization
kTestBitmap = testBitmap();
for (int testStep = 0; testStep < testStepArray().count(); testStep++) {
TestOverrideStateConsistency(reporter, testStepArray()[testStep]);
SkPictureTester::TestPictureSerializationRoundTrip(reporter,
testStepArray()[testStep], 0);
SkPictureTester::TestPictureSerializationRoundTrip(reporter,
testStepArray()[testStep],
SkPicture::kFlattenMutableNonTexturePixelRefs_RecordingFlag);
SkPictureTester::TestPictureFlattenedObjectReuse(reporter,
testStepArray()[testStep], 0);
SkPictureTester::TestPictureFlattenedObjectReuse(reporter,
testStepArray()[testStep],
SkPicture::kFlattenMutableNonTexturePixelRefs_RecordingFlag);
}
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("Canvas", TestCanvasClass, TestCanvas)