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 22 static SkBitmap make_bm(int w, int h) { 23 SkBitmap bm; 24 bm.allocN32Pixels(w, h); 25 return bm; 26 } 27 28 // TODO: can this be derived from SkBaseDevice? 29 class FakeDevice : public SkBitmapDevice { 30 public: 31 FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) { 32 } 33 34 void drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) override { 35 fLastMatrix = *draw.fMatrix; 36 this->INHERITED::drawRect(draw, r, paint); 37 } 38 39 SkMatrix fLastMatrix; 40 41 private: 42 typedef SkBitmapDevice INHERITED; 43 }; 44 45 static void test_frontToBack(skiatest::Reporter* reporter) { 46 SkLayerDrawLooper::Builder looperBuilder; 47 SkLayerDrawLooper::LayerInfo layerInfo; 48 49 // Add the front layer, with the defaults. 50 (void)looperBuilder.addLayer(layerInfo); 51 52 // Add the back layer, with some layer info set. 53 layerInfo.fOffset.set(10.0f, 20.0f); 54 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 55 SkPaint* layerPaint = looperBuilder.addLayer(layerInfo); 56 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 57 58 FakeDevice device; 59 SkCanvas canvas(&device); 60 SkPaint paint; 61 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper()); 62 SkSmallAllocator<1, 32> allocator; 63 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize()); 64 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer); 65 66 // The back layer should come first. 67 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 68 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 69 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 70 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX()); 71 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY()); 72 paint.reset(); 73 74 // Then the front layer. 75 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 76 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 77 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 78 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX()); 79 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY()); 80 81 // Only two layers were added, so that should be the end. 82 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint)); 83 } 84 85 static void test_backToFront(skiatest::Reporter* reporter) { 86 SkLayerDrawLooper::Builder looperBuilder; 87 SkLayerDrawLooper::LayerInfo layerInfo; 88 89 // Add the back layer, with the defaults. 90 (void)looperBuilder.addLayerOnTop(layerInfo); 91 92 // Add the front layer, with some layer info set. 93 layerInfo.fOffset.set(10.0f, 20.0f); 94 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 95 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo); 96 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 97 98 FakeDevice device; 99 SkCanvas canvas(&device); 100 SkPaint paint; 101 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper()); 102 SkSmallAllocator<1, 32> allocator; 103 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize()); 104 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer); 105 106 // The back layer should come first. 107 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 108 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 109 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 110 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX()); 111 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY()); 112 paint.reset(); 113 114 // Then the front layer. 115 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 116 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 117 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 118 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX()); 119 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY()); 120 121 // Only two layers were added, so that should be the end. 122 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint)); 123 } 124 125 static void test_mixed(skiatest::Reporter* reporter) { 126 SkLayerDrawLooper::Builder looperBuilder; 127 SkLayerDrawLooper::LayerInfo layerInfo; 128 129 // Add the back layer, with the defaults. 130 (void)looperBuilder.addLayer(layerInfo); 131 132 // Add the front layer, with some layer info set. 133 layerInfo.fOffset.set(10.0f, 20.0f); 134 layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit; 135 SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo); 136 layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode); 137 138 FakeDevice device; 139 SkCanvas canvas(&device); 140 SkPaint paint; 141 SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper()); 142 SkSmallAllocator<1, 32> allocator; 143 void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize()); 144 SkDrawLooper::Context* context = looper->createContext(&canvas, buffer); 145 146 // The back layer should come first. 147 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 148 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)); 149 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 150 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX()); 151 REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY()); 152 paint.reset(); 153 154 // Then the front layer. 155 REPORTER_ASSERT(reporter, context->next(&canvas, &paint)); 156 REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode)); 157 canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint); 158 REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX()); 159 REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY()); 160 161 // Only two layers were added, so that should be the end. 162 REPORTER_ASSERT(reporter, !context->next(&canvas, &paint)); 163 } 164 165 DEF_TEST(LayerDrawLooper, reporter) { 166 test_frontToBack(reporter); 167 test_backToFront(reporter); 168 test_mixed(reporter); 169 } 170