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 "SkBitmap.h"
9 #include "SkBitmapDevice.h"
10 #include "SkCanvas.h"
11 #include "SkDraw.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 "SkSmallAllocator.h"
19 #include "SkXfermode.h"
20 #include "Test.h"
21
make_bm(int w,int h)22 static SkBitmap make_bm(int w, int h) {
23 SkBitmap bm;
24 bm.allocN32Pixels(w, h);
25 return bm;
26 }
27
28 class FakeDevice : public SkBitmapDevice {
29 public:
FakeDevice()30 FakeDevice() : SkBitmapDevice(make_bm(100, 100)) { }
31
drawRect(const SkDraw & draw,const SkRect & r,const SkPaint & paint)32 virtual void drawRect(const SkDraw& draw, const SkRect& r,
33 const SkPaint& paint) override {
34 fLastMatrix = *draw.fMatrix;
35 this->INHERITED::drawRect(draw, 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->setXfermodeMode(SkXfermode::kSrc_Mode);
56
57 FakeDevice device;
58 SkCanvas canvas(&device);
59 SkPaint paint;
60 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
61 SkSmallAllocator<1, 32> allocator;
62 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
63 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
64
65 // The back layer should come first.
66 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
67 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
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, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
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->setXfermodeMode(SkXfermode::kSrc_Mode);
96
97 FakeDevice device;
98 SkCanvas canvas(&device);
99 SkPaint paint;
100 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
101 SkSmallAllocator<1, 32> allocator;
102 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
103 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
104
105 // The back layer should come first.
106 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
107 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
108 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
109 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
110 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
111 paint.reset();
112
113 // Then the front layer.
114 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
115 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
116 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
117 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
118 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
119
120 // Only two layers were added, so that should be the end.
121 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
122 }
123
test_mixed(skiatest::Reporter * reporter)124 static void test_mixed(skiatest::Reporter* reporter) {
125 SkLayerDrawLooper::Builder looperBuilder;
126 SkLayerDrawLooper::LayerInfo layerInfo;
127
128 // Add the back layer, with the defaults.
129 (void)looperBuilder.addLayer(layerInfo);
130
131 // Add the front layer, with some layer info set.
132 layerInfo.fOffset.set(10.0f, 20.0f);
133 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
134 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
135 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
136
137 FakeDevice device;
138 SkCanvas canvas(&device);
139 SkPaint paint;
140 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
141 SkSmallAllocator<1, 32> allocator;
142 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
143 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
144
145 // The back layer should come first.
146 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
147 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
148 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
149 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
150 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
151 paint.reset();
152
153 // Then the front layer.
154 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
155 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
156 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
157 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
158 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
159
160 // Only two layers were added, so that should be the end.
161 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
162 }
163
DEF_TEST(LayerDrawLooper,reporter)164 DEF_TEST(LayerDrawLooper, reporter) {
165 test_frontToBack(reporter);
166 test_backToFront(reporter);
167 test_mixed(reporter);
168 }
169