/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Test.h" #include "SkBitmap.h" #include "SkBitmapDevice.h" #include "SkCanvas.h" #include "SkDraw.h" #include "SkLayerDrawLooper.h" #include "SkMatrix.h" #include "SkPaint.h" #include "SkRect.h" #include "SkRefCnt.h" #include "SkScalar.h" #include "SkXfermode.h" class FakeDevice : public SkBitmapDevice { public: FakeDevice() : SkBitmapDevice(SkBitmap::kARGB_8888_Config, 100, 100, false) { } virtual void drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) SK_OVERRIDE { fLastMatrix = *draw.fMatrix; INHERITED::drawRect(draw, r, paint); } SkMatrix fLastMatrix; private: typedef SkBitmapDevice INHERITED; }; static void test_frontToBack(skiatest::Reporter* reporter) { SkAutoTUnref looper(SkNEW(SkLayerDrawLooper)); SkLayerDrawLooper::LayerInfo layerInfo; // Add the front layer, with the defaults. (void)looper->addLayer(layerInfo); // Add the back layer, with some layer info set. layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looper->addLayer(layerInfo); layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); FakeDevice device; SkCanvas canvas(&device); SkPaint paint; looper->init(&canvas); // The back layer should come first. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); } static void test_backToFront(skiatest::Reporter* reporter) { SkAutoTUnref looper(SkNEW(SkLayerDrawLooper)); SkLayerDrawLooper::LayerInfo layerInfo; // Add the back layer, with the defaults. (void)looper->addLayerOnTop(layerInfo); // Add the front layer, with some layer info set. layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looper->addLayerOnTop(layerInfo); layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); FakeDevice device; SkCanvas canvas(&device); SkPaint paint; looper->init(&canvas); // The back layer should come first. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); } static void test_mixed(skiatest::Reporter* reporter) { SkAutoTUnref looper(SkNEW(SkLayerDrawLooper)); SkLayerDrawLooper::LayerInfo layerInfo; // Add the back layer, with the defaults. (void)looper->addLayer(layerInfo); // Add the front layer, with some layer info set. layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looper->addLayerOnTop(layerInfo); layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); FakeDevice device; SkCanvas canvas(&device); SkPaint paint; looper->init(&canvas); // The back layer should come first. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); } static void TestLayerDrawLooper(skiatest::Reporter* reporter) { test_frontToBack(reporter); test_backToFront(reporter); test_mixed(reporter); } #include "TestClassDef.h" DEFINE_TESTCLASS("LayerDrawLooper", TestLayerDrawLooperClass, TestLayerDrawLooper)