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
8 #include "include/core/SkBitmap.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkMatrix.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkRect.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/core/SkScalar.h"
15 #include "include/effects/SkLayerDrawLooper.h"
16 #include "src/core/SkArenaAlloc.h"
17 #include "src/core/SkBitmapDevice.h"
18 #include "src/core/SkDraw.h"
19 #include "tests/Test.h"
20
make_bm(int w,int h)21 static SkBitmap make_bm(int w, int h) {
22 SkBitmap bm;
23 bm.allocN32Pixels(w, h);
24 return bm;
25 }
26
27 // TODO: can this be derived from SkBaseDevice?
28 class FakeDevice : public SkBitmapDevice {
29 public:
FakeDevice()30 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry),
31 nullptr, nullptr) {
32 }
33
drawRect(const SkRect & r,const SkPaint & paint)34 void drawRect(const SkRect& r, const SkPaint& paint) override {
35 fLastMatrix = this->ctm();
36 this->INHERITED::drawRect(r, paint);
37 }
38
39 SkMatrix fLastMatrix;
40
41 private:
42 typedef SkBitmapDevice INHERITED;
43 };
44
test_frontToBack(skiatest::Reporter * reporter)45 static void test_frontToBack(skiatest::Reporter* reporter) {
46 SkLayerDrawLooper::Builder looperBuilder;
47 SkLayerDrawLooper::LayerInfo layerInfo;
48
49 // Add the front layer, with the defaults.
50 (void)looperBuilder.addLayer(layerInfo);
51
52 // Add the back layer, with some layer info set.
53 layerInfo.fOffset.set(10.0f, 20.0f);
54 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
55 SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
56 layerPaint->setBlendMode(SkBlendMode::kSrc);
57
58 SkPaint paint;
59 auto looper(looperBuilder.detach());
60 SkArenaAlloc alloc{48};
61 SkDrawLooper::Context* context = looper->makeContext(&alloc);
62 SkDrawLooper::Context::Info info;
63
64 // The back layer should come first.
65 REPORTER_ASSERT(reporter, context->next(&info, &paint));
66 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
67 REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX);
68 REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY);
69 paint.reset();
70
71 // Then the front layer.
72 REPORTER_ASSERT(reporter, context->next(&info, &paint));
73 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
74 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX);
75 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY);
76
77 // Only two layers were added, so that should be the end.
78 REPORTER_ASSERT(reporter, !context->next(&info, &paint));
79 }
80
test_backToFront(skiatest::Reporter * reporter)81 static void test_backToFront(skiatest::Reporter* reporter) {
82 SkLayerDrawLooper::Builder looperBuilder;
83 SkLayerDrawLooper::LayerInfo layerInfo;
84
85 // Add the back layer, with the defaults.
86 (void)looperBuilder.addLayerOnTop(layerInfo);
87
88 // Add the front layer, with some layer info set.
89 layerInfo.fOffset.set(10.0f, 20.0f);
90 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
91 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
92 layerPaint->setBlendMode(SkBlendMode::kSrc);
93
94 SkPaint paint;
95 auto looper(looperBuilder.detach());
96 SkArenaAlloc alloc{48};
97 SkDrawLooper::Context* context = looper->makeContext(&alloc);
98 SkDrawLooper::Context::Info info;
99
100 // The back layer should come first.
101 REPORTER_ASSERT(reporter, context->next(&info, &paint));
102 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
103 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX);
104 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY);
105 paint.reset();
106
107 // Then the front layer.
108 REPORTER_ASSERT(reporter, context->next(&info, &paint));
109 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
110 REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX);
111 REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY);
112
113 // Only two layers were added, so that should be the end.
114 REPORTER_ASSERT(reporter, !context->next(&info, &paint));
115 }
116
test_mixed(skiatest::Reporter * reporter)117 static void test_mixed(skiatest::Reporter* reporter) {
118 SkLayerDrawLooper::Builder looperBuilder;
119 SkLayerDrawLooper::LayerInfo layerInfo;
120
121 // Add the back layer, with the defaults.
122 (void)looperBuilder.addLayer(layerInfo);
123
124 // Add the front layer, with some layer info set.
125 layerInfo.fOffset.set(10.0f, 20.0f);
126 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
127 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
128 layerPaint->setBlendMode(SkBlendMode::kSrc);
129
130 SkPaint paint;
131 sk_sp<SkDrawLooper> looper(looperBuilder.detach());
132 SkArenaAlloc alloc{48};
133 SkDrawLooper::Context* context = looper->makeContext(&alloc);
134 SkDrawLooper::Context::Info info;
135
136 // The back layer should come first.
137 REPORTER_ASSERT(reporter, context->next(&info, &paint));
138 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
139 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fX);
140 REPORTER_ASSERT(reporter, 0.0f == info.fTranslate.fY);
141 paint.reset();
142
143 // Then the front layer.
144 REPORTER_ASSERT(reporter, context->next(&info, &paint));
145 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
146 REPORTER_ASSERT(reporter, 10.0f == info.fTranslate.fX);
147 REPORTER_ASSERT(reporter, 20.0f == info.fTranslate.fY);
148
149 // Only two layers were added, so that should be the end.
150 REPORTER_ASSERT(reporter, !context->next(&info, &paint));
151 }
152
DEF_TEST(LayerDrawLooper,reporter)153 DEF_TEST(LayerDrawLooper, reporter) {
154 test_frontToBack(reporter);
155 test_backToFront(reporter);
156 test_mixed(reporter);
157 }
158