• 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     }
32 
drawRect(const SkRect & r,const SkPaint & paint)33     void drawRect(const SkRect& r, const SkPaint& paint) override {
34         fLastMatrix = this->ctm();
35         this->INHERITED::drawRect(r, paint);
36     }
37 
38     SkMatrix fLastMatrix;
39 
40 private:
41     typedef SkBitmapDevice INHERITED;
42 };
43 
test_frontToBack(skiatest::Reporter * reporter)44 static void test_frontToBack(skiatest::Reporter* reporter) {
45     SkLayerDrawLooper::Builder looperBuilder;
46     SkLayerDrawLooper::LayerInfo layerInfo;
47 
48     // Add the front layer, with the defaults.
49     (void)looperBuilder.addLayer(layerInfo);
50 
51     // Add the back layer, with some layer info set.
52     layerInfo.fOffset.set(10.0f, 20.0f);
53     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
54     SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
55     layerPaint->setBlendMode(SkBlendMode::kSrc);
56 
57     FakeDevice device;
58     SkCanvas canvas(&device);
59     SkPaint paint;
60     auto looper(looperBuilder.detach());
61     SkArenaAlloc alloc{48};
62     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
63 
64     // The back layer should come first.
65     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
66     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
67     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
68     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
69     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
70     paint.reset();
71 
72     // Then the front layer.
73     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
74     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
75     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
76     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
77     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
78 
79     // Only two layers were added, so that should be the end.
80     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
81 }
82 
test_backToFront(skiatest::Reporter * reporter)83 static void test_backToFront(skiatest::Reporter* reporter) {
84     SkLayerDrawLooper::Builder looperBuilder;
85     SkLayerDrawLooper::LayerInfo layerInfo;
86 
87     // Add the back layer, with the defaults.
88     (void)looperBuilder.addLayerOnTop(layerInfo);
89 
90     // Add the front layer, with some layer info set.
91     layerInfo.fOffset.set(10.0f, 20.0f);
92     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
93     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
94     layerPaint->setBlendMode(SkBlendMode::kSrc);
95 
96     FakeDevice device;
97     SkCanvas canvas(&device);
98     SkPaint paint;
99     auto looper(looperBuilder.detach());
100     SkArenaAlloc alloc{48};
101     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
102 
103     // The back layer should come first.
104     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
105     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
106     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
107     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
108     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
109     paint.reset();
110 
111     // Then the front layer.
112     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
113     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
114     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
115     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
116     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
117 
118     // Only two layers were added, so that should be the end.
119     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
120 }
121 
test_mixed(skiatest::Reporter * reporter)122 static void test_mixed(skiatest::Reporter* reporter) {
123     SkLayerDrawLooper::Builder looperBuilder;
124     SkLayerDrawLooper::LayerInfo layerInfo;
125 
126     // Add the back layer, with the defaults.
127     (void)looperBuilder.addLayer(layerInfo);
128 
129     // Add the front layer, with some layer info set.
130     layerInfo.fOffset.set(10.0f, 20.0f);
131     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
132     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
133     layerPaint->setBlendMode(SkBlendMode::kSrc);
134 
135     FakeDevice device;
136     SkCanvas canvas(&device);
137     SkPaint paint;
138     sk_sp<SkDrawLooper> looper(looperBuilder.detach());
139     SkArenaAlloc alloc{48};
140     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
141 
142     // The back layer should come first.
143     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
144     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
145     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
146     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
147     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
148     paint.reset();
149 
150     // Then the front layer.
151     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
152     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
153     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
154     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
155     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
156 
157     // Only two layers were added, so that should be the end.
158     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
159 }
160 
DEF_TEST(LayerDrawLooper,reporter)161 DEF_TEST(LayerDrawLooper, reporter) {
162     test_frontToBack(reporter);
163     test_backToFront(reporter);
164     test_mixed(reporter);
165 }
166