/*
 * 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 "include/core/SkCanvas.h"
#include "include/core/SkDrawLooper.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "src/core/SkArenaAlloc.h"

void SkDrawLooper::Context::Info::applyToCTM(SkMatrix* ctm) const {
    if (fApplyPostCTM) {
        ctm->postTranslate(fTranslate.fX, fTranslate.fY);
    } else {
        ctm->preTranslate(fTranslate.fX, fTranslate.fY);
    }
}

void SkDrawLooper::Context::Info::applyToCanvas(SkCanvas* canvas) const {
    if (fApplyPostCTM) {
        canvas->setMatrix(canvas->getLocalToDevice().postTranslate(fTranslate.fX, fTranslate.fY));
    } else {
        canvas->translate(fTranslate.fX, fTranslate.fY);
    }
}

bool SkDrawLooper::canComputeFastBounds(const SkPaint& paint) const {
    SkSTArenaAlloc<48> alloc;

    SkDrawLooper::Context* context = this->makeContext(&alloc);
    for (;;) {
        SkPaint p(paint);
        SkDrawLooper::Context::Info info;
        if (context->next(&info, &p)) {
            if (!p.canComputeFastBounds()) {
                return false;
            }
        } else {
            break;
        }
    }
    return true;
}

void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& s,
                                     SkRect* dst) const {
    // src and dst rects may alias and we need to keep the original src, so copy it.
    const SkRect src = s;

    SkSTArenaAlloc<48> alloc;

    *dst = src;   // catch case where there are no loops
    SkDrawLooper::Context* context = this->makeContext(&alloc);

    for (bool firstTime = true;; firstTime = false) {
        SkPaint p(paint);
        SkDrawLooper::Context::Info info;
        if (context->next(&info, &p)) {
            SkRect r(src);

            p.computeFastBounds(r, &r);
            r.offset(info.fTranslate.fX, info.fTranslate.fY);

            if (firstTime) {
                *dst = r;
            } else {
                dst->join(r);
            }
        } else {
            break;
        }
    }
}

bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const {
    return false;
}

void SkDrawLooper::apply(SkCanvas* canvas, const SkPaint& paint,
                         std::function<void(SkCanvas*, const SkPaint&)> proc) {
    SkSTArenaAlloc<256> alloc;
    Context* ctx = this->makeContext(&alloc);
    if (ctx) {
        Context::Info info;
        for (;;) {
            SkPaint p = paint;
            if (!ctx->next(&info, &p)) {
                break;
            }
            canvas->save();
            if (info.fApplyPostCTM) {
                canvas->setMatrix(canvas->getLocalToDevice().postTranslate(info.fTranslate.fX,
                                                                           info.fTranslate.fY));
            } else {
                canvas->translate(info.fTranslate.fX, info.fTranslate.fY);
            }
            proc(canvas, p);
            canvas->restore();
        }
    }
}
