/*
 * 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) {
        SkMatrix ctm = canvas->getTotalMatrix();
        ctm.postTranslate(fTranslate.fX, fTranslate.fY);
        canvas->setMatrix(ctm);
    } 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) {
                SkMatrix ctm = canvas->getTotalMatrix();
                ctm.postTranslate(info.fTranslate.fX, info.fTranslate.fY);
                canvas->setMatrix(ctm);
            } else {
                canvas->translate(info.fTranslate.fX, info.fTranslate.fY);
            }
            proc(canvas, p);
            canvas->restore();
        }
    }
}
