/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkDeviceLooper.h"

SkDeviceLooper::SkDeviceLooper(const SkPixmap& base, const SkRasterClip& rc, const SkIRect& bounds,
                               bool aa)
    : fBaseDst(base)
    , fBaseRC(rc)
    , fSubsetRC(rc.isForceConservativeRects())
    , fDelta(aa ? kAA_Delta : kBW_Delta)
{
    // sentinels that next() has not yet been called, and so our mapper functions
    // should not be called either.
    fCurrDst = nullptr;
    fCurrRC = nullptr;

    if (!rc.isEmpty()) {
        // clip must be contained by the bitmap
        SkASSERT(SkIRect::MakeWH(base.width(), base.height()).contains(rc.getBounds()));
    }

    if (rc.isEmpty() || !fClippedBounds.intersect(bounds, rc.getBounds())) {
        fState = kDone_State;
    } else if (this->fitsInDelta(fClippedBounds)) {
        fState = kSimple_State;
    } else {
        // back up by 1 DX, so that next() will put us in a correct starting
        // position.
        fCurrOffset.set(fClippedBounds.left() - fDelta,
                        fClippedBounds.top());
        fState = kComplex_State;
    }
}

SkDeviceLooper::~SkDeviceLooper() {}

void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const {
    SkASSERT(kDone_State != fState);
    SkASSERT(fCurrDst);
    SkASSERT(fCurrRC);

    *dst = src;
    dst->offset(SkIntToScalar(-fCurrOffset.fX),
                SkIntToScalar(-fCurrOffset.fY));
}

void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const {
    SkASSERT(kDone_State != fState);
    SkASSERT(fCurrDst);
    SkASSERT(fCurrRC);

    *dst = src;
    dst->postTranslate(SkIntToScalar(-fCurrOffset.fX), SkIntToScalar(-fCurrOffset.fY));
}

bool SkDeviceLooper::computeCurrBitmapAndClip() {
    SkASSERT(kComplex_State == fState);

    SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
                                  fDelta, fDelta);
    if (!fBaseDst.extractSubset(&fSubsetDst, r)) {
        fSubsetRC.setEmpty();
    } else {
        fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
        (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op);
    }

    fCurrDst = &fSubsetDst;
    fCurrRC = &fSubsetRC;
    return !fCurrRC->isEmpty();
}

static bool next_tile(const SkIRect& boundary, int delta, SkIPoint* offset) {
    // can we move to the right?
    if (offset->x() + delta < boundary.right()) {
        offset->fX += delta;
        return true;
    }

    // reset to the left, but move down a row
    offset->fX = boundary.left();
    if (offset->y() + delta < boundary.bottom()) {
        offset->fY += delta;
        return true;
    }

    // offset is now outside of boundary, so we're done
    return false;
}

bool SkDeviceLooper::next() {
    switch (fState) {
        case kDone_State:
            // in theory, we should not get called here, since we must have
            // previously returned false, but we check anyway.
            break;

        case kSimple_State:
            // first time for simple
            if (nullptr == fCurrDst) {
                fCurrDst = &fBaseDst;
                fCurrRC = &fBaseRC;
                fCurrOffset.set(0, 0);
                return true;
            }
            // 2nd time for simple, we are done
            break;

        case kComplex_State:
            // need to propogate fCurrOffset through clippedbounds
            // left to right, until we wrap around and move down

            while (next_tile(fClippedBounds, fDelta, &fCurrOffset)) {
                if (this->computeCurrBitmapAndClip()) {
                    return true;
                }
            }
            break;
    }
    fState = kDone_State;
    return false;
}
