13d60812865bb034851da777a91413ab584929887reed@google.com/*
23d60812865bb034851da777a91413ab584929887reed@google.com * Copyright 2011 Google Inc.
33d60812865bb034851da777a91413ab584929887reed@google.com *
43d60812865bb034851da777a91413ab584929887reed@google.com * Use of this source code is governed by a BSD-style license that can be
53d60812865bb034851da777a91413ab584929887reed@google.com * found in the LICENSE file.
63d60812865bb034851da777a91413ab584929887reed@google.com */
73d60812865bb034851da777a91413ab584929887reed@google.com
83d60812865bb034851da777a91413ab584929887reed@google.com#include "SkCanvas.h"
93d60812865bb034851da777a91413ab584929887reed@google.com#include "SkDrawLooper.h"
1079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org#include "SkTypes.h"
118f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
123d60812865bb034851da777a91413ab584929887reed@google.com
133d60812865bb034851da777a91413ab584929887reed@google.com/*
143d60812865bb034851da777a91413ab584929887reed@google.com *  Subclass of looper that just draws once, with an offset in X.
153d60812865bb034851da777a91413ab584929887reed@google.com */
163d60812865bb034851da777a91413ab584929887reed@google.comclass TestLooper : public SkDrawLooper {
173d60812865bb034851da777a91413ab584929887reed@google.compublic:
183d60812865bb034851da777a91413ab584929887reed@google.com
1979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    virtual SkDrawLooper::Context* createContext(SkCanvas*, void* storage) const SK_OVERRIDE {
2079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        return SkNEW_PLACEMENT(storage, TestDrawLooperContext);
213d60812865bb034851da777a91413ab584929887reed@google.com    }
223d60812865bb034851da777a91413ab584929887reed@google.com
2379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    virtual size_t contextSize() const SK_OVERRIDE { return sizeof(TestDrawLooperContext); }
243d60812865bb034851da777a91413ab584929887reed@google.com
250f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
264991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    virtual void toString(SkString* str) const SK_OVERRIDE {
274991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com        str->append("TestLooper:");
284991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com    }
294991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com#endif
304991b8f23482afc1494fd17647421ce68de53331robertphillips@google.com
3179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.orgprivate:
3279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    class TestDrawLooperContext : public SkDrawLooper::Context {
3379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    public:
3479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        TestDrawLooperContext() : fOnce(true) {}
3579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        virtual ~TestDrawLooperContext() {}
3679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org
3779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        virtual bool next(SkCanvas* canvas, SkPaint*) SK_OVERRIDE {
3879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            if (fOnce) {
3979fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                fOnce = false;
4079fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                canvas->translate(SkIntToScalar(10), 0);
4179fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org                return true;
4279fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            }
4379fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org            return false;
4479fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        }
4579fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    private:
4679fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org        bool fOnce;
4779fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org    };
4879fbb40bca9d815ef79b896b31ba6ee736817e0fcommit-bot@chromium.org
49ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_UNFLATTENABLE_OBJECT()
503d60812865bb034851da777a91413ab584929887reed@google.com};
513d60812865bb034851da777a91413ab584929887reed@google.com
523d60812865bb034851da777a91413ab584929887reed@google.comstatic void test_drawBitmap(skiatest::Reporter* reporter) {
533d60812865bb034851da777a91413ab584929887reed@google.com    SkBitmap src;
54deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    src.allocN32Pixels(10, 10);
553d60812865bb034851da777a91413ab584929887reed@google.com    src.eraseColor(SK_ColorWHITE);
563d60812865bb034851da777a91413ab584929887reed@google.com
573d60812865bb034851da777a91413ab584929887reed@google.com    SkBitmap dst;
58deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org    dst.allocN32Pixels(10, 10);
59dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    dst.eraseColor(SK_ColorTRANSPARENT);
603d60812865bb034851da777a91413ab584929887reed@google.com
613d60812865bb034851da777a91413ab584929887reed@google.com    SkCanvas canvas(dst);
623d60812865bb034851da777a91413ab584929887reed@google.com    SkPaint  paint;
633d60812865bb034851da777a91413ab584929887reed@google.com
643d60812865bb034851da777a91413ab584929887reed@google.com    // we are initially transparent
653d60812865bb034851da777a91413ab584929887reed@google.com    REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5));
663d60812865bb034851da777a91413ab584929887reed@google.com
673d60812865bb034851da777a91413ab584929887reed@google.com    // we see the bitmap drawn
683d60812865bb034851da777a91413ab584929887reed@google.com    canvas.drawBitmap(src, 0, 0, &paint);
693d60812865bb034851da777a91413ab584929887reed@google.com    REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5));
703d60812865bb034851da777a91413ab584929887reed@google.com
713d60812865bb034851da777a91413ab584929887reed@google.com    // reverify we are clear again
72dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    dst.eraseColor(SK_ColorTRANSPARENT);
733d60812865bb034851da777a91413ab584929887reed@google.com    REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5));
743d60812865bb034851da777a91413ab584929887reed@google.com
753d60812865bb034851da777a91413ab584929887reed@google.com    // if the bitmap is clipped out, we don't draw it
763d60812865bb034851da777a91413ab584929887reed@google.com    canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint);
773d60812865bb034851da777a91413ab584929887reed@google.com    REPORTER_ASSERT(reporter, 0 == *dst.getAddr32(5, 5));
783d60812865bb034851da777a91413ab584929887reed@google.com
793d60812865bb034851da777a91413ab584929887reed@google.com    // now install our looper, which will draw, since it internally translates
803d60812865bb034851da777a91413ab584929887reed@google.com    // to the left. The test is to ensure that canvas' quickReject machinary
813d60812865bb034851da777a91413ab584929887reed@google.com    // allows us through, even though sans-looper we would look like we should
823d60812865bb034851da777a91413ab584929887reed@google.com    // be clipped out.
833d60812865bb034851da777a91413ab584929887reed@google.com    paint.setLooper(new TestLooper)->unref();
843d60812865bb034851da777a91413ab584929887reed@google.com    canvas.drawBitmap(src, SkIntToScalar(-10), 0, &paint);
853d60812865bb034851da777a91413ab584929887reed@google.com    REPORTER_ASSERT(reporter, 0xFFFFFFFF == *dst.getAddr32(5, 5));
863d60812865bb034851da777a91413ab584929887reed@google.com}
873d60812865bb034851da777a91413ab584929887reed@google.com
88e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(QuickReject, reporter) {
893d60812865bb034851da777a91413ab584929887reed@google.com    test_drawBitmap(reporter);
903d60812865bb034851da777a91413ab584929887reed@google.com}
91