1/* 2 * Copyright 2013 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#include "Test.h" 8#include "SkBitmap.h" 9#include "SkCanvas.h" 10#include "SkDraw.h" 11#include "SkDevice.h" 12#include "SkLayerDrawLooper.h" 13#include "SkMatrix.h" 14#include "SkPaint.h" 15#include "SkRect.h" 16#include "SkRefCnt.h" 17#include "SkScalar.h" 18#include "SkXfermode.h" 19 20namespace { 21 22class FakeDevice : public SkDevice { 23public: 24 FakeDevice() : SkDevice(SkBitmap::kARGB_8888_Config, 100, 100) { } 25 26 virtual void drawRect(const SkDraw& draw, const SkRect& r, 27 const SkPaint& paint) SK_OVERRIDE { 28 fLastMatrix = *draw.fMatrix; 29 SkDevice::drawRect(draw, r, paint); 30 } 31 32 SkMatrix fLastMatrix; 33}; 34 35} // namespace 36 37static void test_frontToBack(skiatest::Reporter* reporter) { 38 SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper)); 39 SkLayerDrawLooper::LayerInfo layerInfo; 40 41 // Add the front layer, with the defaults. 42 (void)looper->addLayer(layerInfo); 43 44 // Add the back layer, with some layer info set. 45 layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); 46 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 47 SkPaint* layerPaint = looper->addLayer(layerInfo); 48 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 49 50 FakeDevice device; 51 SkCanvas canvas(&device); 52 SkPaint paint; 53 looper->init(&canvas); 54 55 // The back layer should come first. 56 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 57 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 58 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 59 REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); 60 REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); 61 paint.reset(); 62 63 // Then the front layer. 64 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 65 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 66 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 67 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); 68 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); 69 70 // Only two layers were added, so that should be the end. 71 REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); 72} 73 74static void test_backToFront(skiatest::Reporter* reporter) { 75 SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper)); 76 SkLayerDrawLooper::LayerInfo layerInfo; 77 78 // Add the back layer, with the defaults. 79 (void)looper->addLayerOnTop(layerInfo); 80 81 // Add the front layer, with some layer info set. 82 layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); 83 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 84 SkPaint* layerPaint = looper->addLayerOnTop(layerInfo); 85 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 86 87 FakeDevice device; 88 SkCanvas canvas(&device); 89 SkPaint paint; 90 looper->init(&canvas); 91 92 // The back layer should come first. 93 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 94 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 95 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 96 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); 97 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); 98 paint.reset(); 99 100 // Then the front layer. 101 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 102 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 103 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 104 REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); 105 REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); 106 107 // Only two layers were added, so that should be the end. 108 REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); 109} 110 111static void test_mixed(skiatest::Reporter* reporter) { 112 SkAutoTUnref<SkLayerDrawLooper> looper(SkNEW(SkLayerDrawLooper)); 113 SkLayerDrawLooper::LayerInfo layerInfo; 114 115 // Add the back layer, with the defaults. 116 (void)looper->addLayer(layerInfo); 117 118 // Add the front layer, with some layer info set. 119 layerInfo.fOffset.set(SkFloatToScalar(10.0f), SkFloatToScalar(20.0f)); 120 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 121 SkPaint* layerPaint = looper->addLayerOnTop(layerInfo); 122 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 123 124 FakeDevice device; 125 SkCanvas canvas(&device); 126 SkPaint paint; 127 looper->init(&canvas); 128 129 // The back layer should come first. 130 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 131 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 132 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 133 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateX()); 134 REPORTER_ASSERT(reporter, SkFloatToScalar(0.0f) == device.fLastMatrix.getTranslateY()); 135 paint.reset(); 136 137 // Then the front layer. 138 REPORTER_ASSERT(reporter, looper->next(&canvas, &paint)); 139 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 140 canvas.drawRect(SkRect::MakeWH(SkFloatToScalar(50.0f), SkFloatToScalar(50.0f)), paint); 141 REPORTER_ASSERT(reporter, SkFloatToScalar(10.0f) == device.fLastMatrix.getTranslateX()); 142 REPORTER_ASSERT(reporter, SkFloatToScalar(20.0f) == device.fLastMatrix.getTranslateY()); 143 144 // Only two layers were added, so that should be the end. 145 REPORTER_ASSERT(reporter, !looper->next(&canvas, &paint)); 146} 147 148static void TestLayerDrawLooper(skiatest::Reporter* reporter) { 149 test_frontToBack(reporter); 150 test_backToFront(reporter); 151 test_mixed(reporter); 152} 153 154#include "TestClassDef.h" 155DEFINE_TESTCLASS("LayerDrawLooper", TestLayerDrawLooperClass, TestLayerDrawLooper) 156