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 "SkArenaAlloc.h"
      9 #include "SkBitmap.h"
     10 #include "SkBitmapDevice.h"
     11 #include "SkCanvas.h"
     12 #include "SkDraw.h"
     13 #include "SkLayerDrawLooper.h"
     14 #include "SkMatrix.h"
     15 #include "SkPaint.h"
     16 #include "SkRect.h"
     17 #include "SkRefCnt.h"
     18 #include "SkScalar.h"
     19 #include "Test.h"
     20 
     21 static SkBitmap make_bm(int w, int h) {
     22     SkBitmap bm;
     23     bm.allocN32Pixels(w, h);
     24     return bm;
     25 }
     26 
     27 // TODO: can this be derived from SkBaseDevice?
     28 class FakeDevice : public SkBitmapDevice {
     29 public:
     30     FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry),
     31                              nullptr, nullptr) {
     32     }
     33 
     34     void drawRect(const SkRect& r, const SkPaint& paint) override {
     35         fLastMatrix = this->ctm();
     36         this->INHERITED::drawRect(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->setBlendMode(SkBlendMode::kSrc);
     57 
     58     FakeDevice device;
     59     SkCanvas canvas(sk_ref_sp(&device));
     60     SkPaint paint;
     61     auto looper(looperBuilder.detach());
     62     SkArenaAlloc alloc{48};
     63     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
     64 
     65     // The back layer should come first.
     66     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
     67     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
     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, paint.getBlendMode() == SkBlendMode::kSrcOver);
     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->setBlendMode(SkBlendMode::kSrc);
     96 
     97     FakeDevice device;
     98     SkCanvas canvas(sk_ref_sp(&device));
     99     SkPaint paint;
    100     auto looper(looperBuilder.detach());
    101     SkArenaAlloc alloc{48};
    102     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
    103 
    104     // The back layer should come first.
    105     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    106     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
    107     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    108     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
    109     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
    110     paint.reset();
    111 
    112     // Then the front layer.
    113     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    114     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
    115     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    116     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
    117     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
    118 
    119     // Only two layers were added, so that should be the end.
    120     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
    121 }
    122 
    123 static void test_mixed(skiatest::Reporter* reporter) {
    124     SkLayerDrawLooper::Builder looperBuilder;
    125     SkLayerDrawLooper::LayerInfo layerInfo;
    126 
    127     // Add the back layer, with the defaults.
    128     (void)looperBuilder.addLayer(layerInfo);
    129 
    130     // Add the front layer, with some layer info set.
    131     layerInfo.fOffset.set(10.0f, 20.0f);
    132     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
    133     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
    134     layerPaint->setBlendMode(SkBlendMode::kSrc);
    135 
    136     FakeDevice device;
    137     SkCanvas canvas(sk_ref_sp(&device));
    138     SkPaint paint;
    139     sk_sp<SkDrawLooper> looper(looperBuilder.detach());
    140     SkArenaAlloc alloc{48};
    141     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
    142 
    143     // The back layer should come first.
    144     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    145     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
    146     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    147     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
    148     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
    149     paint.reset();
    150 
    151     // Then the front layer.
    152     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    153     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
    154     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    155     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
    156     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
    157 
    158     // Only two layers were added, so that should be the end.
    159     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
    160 }
    161 
    162 DEF_TEST(LayerDrawLooper, reporter) {
    163     test_frontToBack(reporter);
    164     test_backToFront(reporter);
    165     test_mixed(reporter);
    166 }
    167