blob: 8fcbf1615cd1161212a575dc34f93887b7639821 [file] [log] [blame]
commit-bot@chromium.org8f838252013-05-22 12:35:50 +00001/*
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 */
commit-bot@chromium.orgddf94cf2013-10-12 17:25:17 +00007
commit-bot@chromium.org8f838252013-05-22 12:35:50 +00008#include "SkBitmap.h"
Mike Reed986480a2017-01-13 22:43:16 +00009#include "SkBitmapDevice.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000010#include "SkCanvas.h"
11#include "SkDraw.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000012#include "SkLayerDrawLooper.h"
13#include "SkMatrix.h"
14#include "SkPaint.h"
15#include "SkRect.h"
16#include "SkRefCnt.h"
17#include "SkScalar.h"
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000018#include "SkSmallAllocator.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000019#include "Test.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000020
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000021static SkBitmap make_bm(int w, int h) {
22 SkBitmap bm;
23 bm.allocN32Pixels(w, h);
24 return bm;
25}
26
robertphillips9a53fd72015-06-22 09:46:59 -070027// TODO: can this be derived from SkBaseDevice?
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000028class FakeDevice : public SkBitmapDevice {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000029public:
robertphillips9a53fd72015-06-22 09:46:59 -070030 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) {
31 }
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000032
robertphillips9a53fd72015-06-22 09:46:59 -070033 void drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) override {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000034 fLastMatrix = *draw.fMatrix;
robertphillips@google.com84b18c72014-04-13 19:09:42 +000035 this->INHERITED::drawRect(draw, r, paint);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000036 }
37
38 SkMatrix fLastMatrix;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000039
40private:
41 typedef SkBitmapDevice INHERITED;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000042};
43
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000044static void test_frontToBack(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000045 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000046 SkLayerDrawLooper::LayerInfo layerInfo;
47
48 // Add the front layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000049 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000050
51 // Add the back layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000052 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000053 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000054 SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
reed374772b2016-10-05 17:33:02 -070055 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000056
57 FakeDevice device;
58 SkCanvas canvas(&device);
59 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -070060 auto looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000061 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -080062 SkDrawLooper::Context* context = allocator.createWithIniter(
63 looper->contextSize(),
64 [&](void* buffer) {
65 return looper->createContext(&canvas, buffer);
66 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000067
68 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000069 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070070 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000071 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
72 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
73 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000074 paint.reset();
75
76 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000077 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070078 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000079 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
80 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
81 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000082
83 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000084 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000085}
86
87static void test_backToFront(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000088 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000089 SkLayerDrawLooper::LayerInfo layerInfo;
90
91 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000092 (void)looperBuilder.addLayerOnTop(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000093
94 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000095 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000096 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000097 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -070098 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000099
100 FakeDevice device;
101 SkCanvas canvas(&device);
102 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700103 auto looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000104 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -0800105 SkDrawLooper::Context* context = allocator.createWithIniter(
106 looper->contextSize(),
107 [&](void* buffer) {
108 return looper->createContext(&canvas, buffer);
109 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000110
111 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000112 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700113 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000114 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
115 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
116 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000117 paint.reset();
118
119 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000120 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700121 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000122 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
123 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
124 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000125
126 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000127 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000128}
129
130static void test_mixed(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000131 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000132 SkLayerDrawLooper::LayerInfo layerInfo;
133
134 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000135 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000136
137 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000138 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000139 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000140 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -0700141 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000142
143 FakeDevice device;
144 SkCanvas canvas(&device);
145 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700146 sk_sp<SkDrawLooper> looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000147 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -0800148 SkDrawLooper::Context* context = allocator.createWithIniter(
149 looper->contextSize(),
150 [&](void* buffer) {
151 return looper->createContext(&canvas, buffer);
152 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000153
154 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000155 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700156 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000157 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
158 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
159 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000160 paint.reset();
161
162 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000163 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700164 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000165 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
166 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
167 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000168
169 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000170 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000171}
172
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000173DEF_TEST(LayerDrawLooper, reporter) {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000174 test_frontToBack(reporter);
175 test_backToFront(reporter);
176 test_mixed(reporter);
177}