blob: 7b3aa298832bd09ecd4f07459fabf1285841797e [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"
robertphillips@google.com1f2f3382013-08-29 11:54:56 +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"
Greg Daniele9d1b292016-11-23 16:47:38 +000019#include "SkXfermode.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +000020#include "Test.h"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000021
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000022static SkBitmap make_bm(int w, int h) {
23 SkBitmap bm;
24 bm.allocN32Pixels(w, h);
25 return bm;
26}
27
robertphillips9a53fd72015-06-22 09:46:59 -070028// TODO: can this be derived from SkBaseDevice?
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000029class FakeDevice : public SkBitmapDevice {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000030public:
robertphillips9a53fd72015-06-22 09:46:59 -070031 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) {
32 }
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000033
robertphillips9a53fd72015-06-22 09:46:59 -070034 void drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) override {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000035 fLastMatrix = *draw.fMatrix;
robertphillips@google.com84b18c72014-04-13 19:09:42 +000036 this->INHERITED::drawRect(draw, 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;
59 SkCanvas canvas(&device);
60 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -070061 auto looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000062 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -080063 SkDrawLooper::Context* context = allocator.createWithIniter(
64 looper->contextSize(),
65 [&](void* buffer) {
66 return looper->createContext(&canvas, buffer);
67 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000068
69 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000070 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070071 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000072 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
73 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
74 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000075 paint.reset();
76
77 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000078 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -070079 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000080 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
81 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
82 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000083
84 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000085 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000086}
87
88static void test_backToFront(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000089 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000090 SkLayerDrawLooper::LayerInfo layerInfo;
91
92 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000093 (void)looperBuilder.addLayerOnTop(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000094
95 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000096 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000097 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000098 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -070099 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000100
101 FakeDevice device;
102 SkCanvas canvas(&device);
103 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700104 auto looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000105 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -0800106 SkDrawLooper::Context* context = allocator.createWithIniter(
107 looper->contextSize(),
108 [&](void* buffer) {
109 return looper->createContext(&canvas, buffer);
110 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000111
112 // The back layer should come first.
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::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000115 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
116 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
117 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000118 paint.reset();
119
120 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000121 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700122 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000123 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
124 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
125 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000126
127 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000128 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000129}
130
131static void test_mixed(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000132 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000133 SkLayerDrawLooper::LayerInfo layerInfo;
134
135 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000136 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000137
138 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000139 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000140 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000141 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
reed374772b2016-10-05 17:33:02 -0700142 layerPaint->setBlendMode(SkBlendMode::kSrc);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000143
144 FakeDevice device;
145 SkCanvas canvas(&device);
146 SkPaint paint;
reed7b380d02016-03-21 13:25:16 -0700147 sk_sp<SkDrawLooper> looper(looperBuilder.detach());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000148 SkSmallAllocator<1, 32> allocator;
herbbf6d80a2016-11-15 06:26:56 -0800149 SkDrawLooper::Context* context = allocator.createWithIniter(
150 looper->contextSize(),
151 [&](void* buffer) {
152 return looper->createContext(&canvas, buffer);
153 });
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000154
155 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000156 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700157 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000158 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
159 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
160 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000161 paint.reset();
162
163 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000164 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
reed374772b2016-10-05 17:33:02 -0700165 REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000166 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
167 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
168 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000169
170 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000171 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000172}
173
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000174DEF_TEST(LayerDrawLooper, reporter) {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000175 test_frontToBack(reporter);
176 test_backToFront(reporter);
177 test_mixed(reporter);
178}