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