• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkArenaAlloc.h"
9 #include "SkBitmap.h"
10 #include "SkBitmapDevice.h"
11 #include "SkCanvas.h"
12 #include "SkDraw.h"
13 #include "SkLayerDrawLooper.h"
14 #include "SkMatrix.h"
15 #include "SkPaint.h"
16 #include "SkRect.h"
17 #include "SkRefCnt.h"
18 #include "SkScalar.h"
19 #include "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     FakeDevice device;
59     SkCanvas canvas(sk_ref_sp(&device));
60     SkPaint paint;
61     auto looper(looperBuilder.detach());
62     SkArenaAlloc alloc{48};
63     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
64 
65     // The back layer should come first.
66     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
67     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
68     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
69     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
70     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
71     paint.reset();
72 
73     // Then the front layer.
74     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
75     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
76     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
77     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
78     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
79 
80     // Only two layers were added, so that should be the end.
81     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
82 }
83 
test_backToFront(skiatest::Reporter * reporter)84 static void test_backToFront(skiatest::Reporter* reporter) {
85     SkLayerDrawLooper::Builder looperBuilder;
86     SkLayerDrawLooper::LayerInfo layerInfo;
87 
88     // Add the back layer, with the defaults.
89     (void)looperBuilder.addLayerOnTop(layerInfo);
90 
91     // Add the front layer, with some layer info set.
92     layerInfo.fOffset.set(10.0f, 20.0f);
93     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
94     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
95     layerPaint->setBlendMode(SkBlendMode::kSrc);
96 
97     FakeDevice device;
98     SkCanvas canvas(sk_ref_sp(&device));
99     SkPaint paint;
100     auto looper(looperBuilder.detach());
101     SkArenaAlloc alloc{48};
102     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
103 
104     // The back layer should come first.
105     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
106     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
107     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
108     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
109     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
110     paint.reset();
111 
112     // Then the front layer.
113     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
114     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
115     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
116     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
117     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
118 
119     // Only two layers were added, so that should be the end.
120     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
121 }
122 
test_mixed(skiatest::Reporter * reporter)123 static void test_mixed(skiatest::Reporter* reporter) {
124     SkLayerDrawLooper::Builder looperBuilder;
125     SkLayerDrawLooper::LayerInfo layerInfo;
126 
127     // Add the back layer, with the defaults.
128     (void)looperBuilder.addLayer(layerInfo);
129 
130     // Add the front layer, with some layer info set.
131     layerInfo.fOffset.set(10.0f, 20.0f);
132     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
133     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
134     layerPaint->setBlendMode(SkBlendMode::kSrc);
135 
136     FakeDevice device;
137     SkCanvas canvas(sk_ref_sp(&device));
138     SkPaint paint;
139     sk_sp<SkDrawLooper> looper(looperBuilder.detach());
140     SkArenaAlloc alloc{48};
141     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
142 
143     // The back layer should come first.
144     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
145     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
146     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
147     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
148     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
149     paint.reset();
150 
151     // Then the front layer.
152     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
153     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
154     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
155     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
156     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
157 
158     // Only two layers were added, so that should be the end.
159     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
160 }
161 
DEF_TEST(LayerDrawLooper,reporter)162 DEF_TEST(LayerDrawLooper, reporter) {
163     test_frontToBack(reporter);
164     test_backToFront(reporter);
165     test_mixed(reporter);
166 }
167