/* * 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 "include/core/SkBitmap.h" #include "include/core/SkCanvas.h" #include "include/core/SkMatrix.h" #include "include/core/SkPaint.h" #include "include/core/SkRect.h" #include "include/core/SkRefCnt.h" #include "include/core/SkScalar.h" #include "include/effects/SkLayerDrawLooper.h" #include "src/core/SkArenaAlloc.h" #include "src/core/SkBitmapDevice.h" #include "src/core/SkDraw.h" #include "tests/Test.h" static SkBitmap make_bm(int w, int h) { SkBitmap bm; bm.allocN32Pixels(w, h); return bm; } // TODO: can this be derived from SkBaseDevice? class FakeDevice : public SkBitmapDevice { public: FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry), nullptr, nullptr) { } void drawRect(const SkRect& r, const SkPaint& paint) override { fLastMatrix = this->localToDevice(); this->INHERITED::drawRect(r, paint); } SkMatrix fLastMatrix; private: using INHERITED = SkBitmapDevice; }; static void test_frontToBack(skiatest::Reporter* reporter) { SkLayerDrawLooper::Builder looperBuilder; SkLayerDrawLooper::LayerInfo layerInfo; // Add the front layer, with the defaults. (void)looperBuilder.addLayer(layerInfo); // Add the back layer, with some layer info set. layerInfo.fOffset.set(10.0f, 20.0f); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looperBuilder.addLayer(layerInfo); layerPaint->setBlendMode(SkBlendMode::kSrc); SkPaint paint; auto looper(looperBuilder.detach()); SkArenaAlloc alloc{48}; SkDrawLooper::Context* context = looper->makeContext(&alloc); SkDrawLooper::Context::Info info; // The back layer should come first. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc); REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !context->next(&info, &paint)); } static void test_backToFront(skiatest::Reporter* reporter) { SkLayerDrawLooper::Builder looperBuilder; SkLayerDrawLooper::LayerInfo layerInfo; // Add the back layer, with the defaults. (void)looperBuilder.addLayerOnTop(layerInfo); // Add the front layer, with some layer info set. layerInfo.fOffset.set(10.0f, 20.0f); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo); layerPaint->setBlendMode(SkBlendMode::kSrc); SkPaint paint; auto looper(looperBuilder.detach()); SkArenaAlloc alloc{48}; SkDrawLooper::Context* context = looper->makeContext(&alloc); SkDrawLooper::Context::Info info; // The back layer should come first. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc); REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !context->next(&info, &paint)); } static void test_mixed(skiatest::Reporter* reporter) { SkLayerDrawLooper::Builder looperBuilder; SkLayerDrawLooper::LayerInfo layerInfo; // Add the back layer, with the defaults. (void)looperBuilder.addLayer(layerInfo); // Add the front layer, with some layer info set. layerInfo.fOffset.set(10.0f, 20.0f); layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo); layerPaint->setBlendMode(SkBlendMode::kSrc); SkPaint paint; sk_sp looper(looperBuilder.detach()); SkArenaAlloc alloc{48}; SkDrawLooper::Context* context = looper->makeContext(&alloc); SkDrawLooper::Context::Info info; // The back layer should come first. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY); paint.reset(); // Then the front layer. REPORTER_ASSERT(reporter, context->next(&info, &paint)); REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc); REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX); REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY); // Only two layers were added, so that should be the end. REPORTER_ASSERT(reporter, !context->next(&info, &paint)); } DEF_TEST(LayerDrawLooper, reporter) { test_frontToBack(reporter); test_backToFront(reporter); test_mixed(reporter); }