blob: bc76a02a4bfd3d2845f03ca5a28501cd7d522b20 [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"
commit-bot@chromium.org8f838252013-05-22 12:35:50 +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
robertphillips@google.com1f2f3382013-08-29 11:54:56 +000028class FakeDevice : public SkBitmapDevice {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000029public:
commit-bot@chromium.org15a14052014-02-16 00:59:25 +000030 FakeDevice() : SkBitmapDevice(make_bm(100, 100)) { }
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000031
skia.committer@gmail.com7f1af502013-07-24 07:01:12 +000032 virtual void drawRect(const SkDraw& draw, const SkRect& r,
commit-bot@chromium.org3e2ea252013-07-23 11:28:45 +000033 const SkPaint& paint) SK_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);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000055 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
56
57 FakeDevice device;
58 SkCanvas canvas(&device);
59 SkPaint paint;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +000060 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +000061 SkSmallAllocator<1, 32> allocator;
62 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
63 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
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));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000067 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
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));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000075 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
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);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +000095 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
96
97 FakeDevice device;
98 SkCanvas canvas(&device);
99 SkPaint paint;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000100 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000101 SkSmallAllocator<1, 32> allocator;
102 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
103 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000104
105 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000106 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000107 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000108 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000111 paint.reset();
112
113 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000114 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000115 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000116 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000119
120 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000121 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000122}
123
124static void test_mixed(skiatest::Reporter* reporter) {
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000125 SkLayerDrawLooper::Builder looperBuilder;
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000126 SkLayerDrawLooper::LayerInfo layerInfo;
127
128 // Add the back layer, with the defaults.
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000129 (void)looperBuilder.addLayer(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000130
131 // Add the front layer, with some layer info set.
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000132 layerInfo.fOffset.set(10.0f, 20.0f);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000133 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000134 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000135 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
136
137 FakeDevice device;
138 SkCanvas canvas(&device);
139 SkPaint paint;
commit-bot@chromium.org74ba2f62014-02-14 10:06:42 +0000140 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000141 SkSmallAllocator<1, 32> allocator;
142 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
143 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000144
145 // The back layer should come first.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000146 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000147 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000148 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000151 paint.reset();
152
153 // Then the front layer.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000154 REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000155 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000156 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());
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000159
160 // Only two layers were added, so that should be the end.
commit-bot@chromium.org79fbb402014-03-12 09:42:01 +0000161 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000162}
163
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +0000164DEF_TEST(LayerDrawLooper, reporter) {
commit-bot@chromium.org8f838252013-05-22 12:35:50 +0000165 test_frontToBack(reporter);
166 test_backToFront(reporter);
167 test_mixed(reporter);
168}