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 // 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