blob: e0d082a9f510189d85175686f81e0d276deb256e [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
Herb Derby73fe7b02017-02-08 15:12:19 -05008#include "SkArenaAlloc.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +00009#include "SkBitmap.h"
Mike Reed986480a2017-01-13 22:43:16 +000010#include "SkBitmapDevice.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000011#include "SkCanvas.h"
12#include "SkDraw.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000013#include "SkLayerDrawLooper.h"
14#include "SkMatrix.h"
15#include "SkPaint.h"
16#include "SkRect.h"
17#include "SkRefCnt.h"
18#include "SkScalar.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:
Mike Reed910ca0f2018-04-25 13:04:05 -040030 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry),
31 nullptr, nullptr) {
robertphillips9a53fd72015-06-22 09:46:59 -070032 }
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000033
Mike Reeda1361362017-03-07 09:37:29 -050034 void drawRect(const SkRect& r, const SkPaint& paint) override {
35 fLastMatrix = this->ctm();
36 this->INHERITED::drawRect(r, paint);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000037 }
38
39 SkMatrix fLastMatrix;
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000040
41private:
42 typedef SkBitmapDevice INHERITED;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000043};
44
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000045static void test_frontToBack(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000046 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000047 SkLayerDrawLooper::LayerInfo layerInfo;
48
49 // Add the front layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000050 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000051
52 // Add the back layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000053 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000054 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000055 SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
reed374772b2016-10-05 17:33:02 -070056 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000057
58 FakeDevice device;
Herb Derbyefe39bc2018-05-01 17:06:20 -040059 SkCanvas canvas(sk_ref_sp(&device));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000060 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -070061 auto looper(looperBuilder.detach());
Herb Derby73fe7b02017-02-08 15:12:19 -050062 SkArenaAlloc alloc{48};
63 SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000064
65 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000066 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070067 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000068 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000071 paint.reset();
72
73 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000074 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070075 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000076 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000079
80 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000081 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000082}
83
84static void test_backToFront(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000085 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000086 SkLayerDrawLooper::LayerInfo layerInfo;
87
88 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000089 (void)looperBuilder.addLayerOnTop(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000090
91 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000092 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000093 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000094 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -070095 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000096
97 FakeDevice device;
Herb Derbyefe39bc2018-05-01 17:06:20 -040098 SkCanvas canvas(sk_ref_sp(&device));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000099 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700100 auto looper(looperBuilder.detach());
Herb Derby73fe7b02017-02-08 15:12:19 -0500101 SkArenaAlloc alloc{48};
102 SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000103
104 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000105 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700106 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000107 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000110 paint.reset();
111
112 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000113 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700114 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000115 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000118
119 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000120 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000121}
122
123static void test_mixed(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000124 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000125 SkLayerDrawLooper::LayerInfo layerInfo;
126
127 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000128 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000129
130 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000131 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000132 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000133 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -0700134 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000135
136 FakeDevice device;
Herb Derbyefe39bc2018-05-01 17:06:20 -0400137 SkCanvas canvas(sk_ref_sp(&device));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000138 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700139 sk_sp<SkDrawLooper> looper(looperBuilder.detach());
Herb Derby73fe7b02017-02-08 15:12:19 -0500140 SkArenaAlloc alloc{48};
141 SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000142
143 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000144 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700145 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000146 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000149 paint.reset();
150
151 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000152 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700153 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000154 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000157
158 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000159 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000160}
161
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000162DEF_TEST(LayerDrawLooper, reporter) {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000163 test_frontToBack(reporter);
164 test_backToFront(reporter);
165 test_mixed(reporter);
166}