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     }
     32 
     33     void drawRect(const SkRect& r, const SkPaint& paint) override {
     34         fLastMatrix = this->ctm();
     35         this->INHERITED::drawRect(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->setBlendMode(SkBlendMode::kSrc);
     56 
     57     FakeDevice device;
     58     SkCanvas canvas(&device);
     59     SkPaint paint;
     60     auto looper(looperBuilder.detach());
     61     SkArenaAlloc alloc{48};
     62     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
     63 
     64     // The back layer should come first.
     65     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
     66     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
     67     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     68     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
     69     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
     70     paint.reset();
     71 
     72     // Then the front layer.
     73     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
     74     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
     75     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
     76     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
     77     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
     78 
     79     // Only two layers were added, so that should be the end.
     80     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
     81 }
     82 
     83 static void test_backToFront(skiatest::Reporter* reporter) {
     84     SkLayerDrawLooper::Builder looperBuilder;
     85     SkLayerDrawLooper::LayerInfo layerInfo;
     86 
     87     // Add the back layer, with the defaults.
     88     (void)looperBuilder.addLayerOnTop(layerInfo);
     89 
     90     // Add the front layer, with some layer info set.
     91     layerInfo.fOffset.set(10.0f, 20.0f);
     92     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
     93     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
     94     layerPaint->setBlendMode(SkBlendMode::kSrc);
     95 
     96     FakeDevice device;
     97     SkCanvas canvas(&device);
     98     SkPaint paint;
     99     auto looper(looperBuilder.detach());
    100     SkArenaAlloc alloc{48};
    101     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
    102 
    103     // The back layer should come first.
    104     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    105     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
    106     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    107     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
    108     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
    109     paint.reset();
    110 
    111     // Then the front layer.
    112     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    113     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
    114     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    115     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
    116     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
    117 
    118     // Only two layers were added, so that should be the end.
    119     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
    120 }
    121 
    122 static void test_mixed(skiatest::Reporter* reporter) {
    123     SkLayerDrawLooper::Builder looperBuilder;
    124     SkLayerDrawLooper::LayerInfo layerInfo;
    125 
    126     // Add the back layer, with the defaults.
    127     (void)looperBuilder.addLayer(layerInfo);
    128 
    129     // Add the front layer, with some layer info set.
    130     layerInfo.fOffset.set(10.0f, 20.0f);
    131     layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
    132     SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
    133     layerPaint->setBlendMode(SkBlendMode::kSrc);
    134 
    135     FakeDevice device;
    136     SkCanvas canvas(&device);
    137     SkPaint paint;
    138     sk_sp<SkDrawLooper> looper(looperBuilder.detach());
    139     SkArenaAlloc alloc{48};
    140     SkDrawLooper::Context* context = looper->makeContext(&canvas, &alloc);
    141 
    142     // The back layer should come first.
    143     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    144     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrcOver);
    145     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    146     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
    147     REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
    148     paint.reset();
    149 
    150     // Then the front layer.
    151     REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
    152     REPORTER_ASSERT(reporter, paint.getBlendMode() == SkBlendMode::kSrc);
    153     canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
    154     REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
    155     REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
    156 
    157     // Only two layers were added, so that should be the end.
    158     REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
    159 }
    160 
    161 DEF_TEST(LayerDrawLooper, reporter) {
    162     test_frontToBack(reporter);
    163     test_backToFront(reporter);
    164     test_mixed(reporter);
    165 }
    166