Home | History | Annotate | Download | only in tests
      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) 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