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

#include "modules/sksg/include/SkSGRenderNode.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkImageFilter.h"
#include "include/core/SkPaint.h"
#include "modules/sksg/src/SkSGNodePriv.h"

namespace sksg {

namespace {

enum Flags : uint8_t {
    kInvisible_Flag = 1 << 0,
};

} // namespace

RenderNode::RenderNode(uint32_t inval_traits) : INHERITED(inval_traits) {}

bool RenderNode::isVisible() const {
    return !(fNodeFlags & kInvisible_Flag);
}

void RenderNode::setVisible(bool v) {
    if (v == this->isVisible()) {
        return;
    }

    this->invalidate();
    fNodeFlags = v ? (fNodeFlags & ~kInvisible_Flag)
                   : (fNodeFlags | kInvisible_Flag);
}

void RenderNode::render(SkCanvas* canvas, const RenderContext* ctx) const {
    SkASSERT(!this->hasInval());
    if (this->isVisible() && !this->bounds().isEmpty()) {
        this->onRender(canvas, ctx);
    }
    SkASSERT(!this->hasInval());
}

const RenderNode* RenderNode::nodeAt(const SkPoint& p) const {
    return this->bounds().contains(p.x(), p.y()) ? this->onNodeAt(p) : nullptr;
}

static SkAlpha ScaleAlpha(SkAlpha alpha, float opacity) {
   return SkToU8(sk_float_round2int(alpha * opacity));
}

static sk_sp<SkShader> LocalShader(const sk_sp<SkShader> shader,
                                   const SkMatrix& base,
                                   const SkMatrix& ctm) {
    // Mask filters / shaders are declared to operate under a specific transform, but due to the
    // deferral mechanism, other transformations might have been pushed to the state.
    // We want to undo these transforms (T):
    //
    //   baseCTM x T = ctm
    //
    //   =>  T = Inv(baseCTM) x ctm
    //
    //   =>  Inv(T) = Inv(Inv(baseCTM) x ctm)
    //
    //   =>  Inv(T) = Inv(ctm) x baseCTM

    SkMatrix lm;
    if (base != ctm && ctm.invert(&lm)) {
        lm.preConcat(base);
    } else {
        lm = SkMatrix::I();
    }

    // Note: this doesn't play ball with existing shader local matrices (what we really want is
    // SkShader::makeWithPostLocalMatrix).  Probably a good signal that the whole mechanism is
    // contrived and should be redesigned (use SkCanvas::clipShader when available, drop shader
    // "effects" completely, etc).
    return shader->makeWithLocalMatrix(lm);
}

bool RenderNode::RenderContext::requiresIsolation() const {
    // Note: fShader is never applied on isolation layers.
    return ScaleAlpha(SK_AlphaOPAQUE, fOpacity) != SK_AlphaOPAQUE
        || fColorFilter
        || fMaskShader
        || fBlendMode != SkBlendMode::kSrcOver;
}

void RenderNode::RenderContext::modulatePaint(const SkMatrix& ctm, SkPaint* paint,
                                              bool is_layer_paint) const {
    paint->setAlpha(ScaleAlpha(paint->getAlpha(), fOpacity));
    paint->setColorFilter(SkColorFilters::Compose(fColorFilter, paint->refColorFilter()));
    if (fShader) {
        paint->setShader(LocalShader(fShader, fShaderCTM, ctm));
    }
    if (fBlendMode != SkBlendMode::kSrcOver) {
        paint->setBlendMode(fBlendMode);
    }

    // Only apply the shader mask for regular paints.  Isolation layers require
    // special handling on restore.
    if (!is_layer_paint && fMaskShader) {
        paint->setShader(SkShaders::Blend(SkBlendMode::kSrcIn,
                                          LocalShader(fMaskShader, fMaskCTM, ctm),
                                          paint->refShader()));
    }
}

RenderNode::ScopedRenderContext::ScopedRenderContext(SkCanvas* canvas, const RenderContext* ctx)
    : fCanvas(canvas)
    , fCtx(ctx ? *ctx : RenderContext())
    , fRestoreCount(canvas->getSaveCount()) {}

RenderNode::ScopedRenderContext::~ScopedRenderContext() {
    if (fRestoreCount >= 0) {
        if (fMaskShader) {
            SkPaint mask_paint;
            mask_paint.setBlendMode(SkBlendMode::kDstIn);
            mask_paint.setShader(std::move(fMaskShader));
            fCanvas->drawPaint(mask_paint);
        }
        fCanvas->restoreToCount(fRestoreCount);
    }
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::modulateOpacity(float opacity) {
    SkASSERT(opacity >= 0 && opacity <= 1);
    fCtx.fOpacity *= opacity;
    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::modulateColorFilter(sk_sp<SkColorFilter> cf) {
    fCtx.fColorFilter = SkColorFilters::Compose(std::move(fCtx.fColorFilter), std::move(cf));
    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::modulateShader(sk_sp<SkShader> sh, const SkMatrix& shader_ctm) {
    // Topmost shader takes precedence.
    if (!fCtx.fShader) {
        fCtx.fShader = std::move(sh);
        fCtx.fShaderCTM = shader_ctm;
    }

    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::modulateMaskShader(sk_sp<SkShader> ms, const SkMatrix& ctm) {
    if (fCtx.fMaskShader) {
        // As we compose mask filters, use the relative transform T for the inner mask:
        //
        //   maskCTM x T = ctm
        //
        //   => T = Inv(maskCTM) x ctm
        //
        SkMatrix invMaskCTM;
        if (ms && fCtx.fMaskCTM.invert(&invMaskCTM)) {
            const auto relative_transform = SkMatrix::Concat(invMaskCTM, ctm);
            fCtx.fMaskShader = SkShaders::Blend(SkBlendMode::kSrcIn,
                                                std::move(fCtx.fMaskShader),
                                                ms->makeWithLocalMatrix(relative_transform));
        }
    } else {
        fCtx.fMaskShader = std::move(ms);
        fCtx.fMaskCTM    = ctm;
    }

    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::modulateBlendMode(SkBlendMode mode) {
    fCtx.fBlendMode = mode;
    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::setIsolation(const SkRect& bounds, const SkMatrix& ctm,
                                              bool isolation) {
    if (isolation && fCtx.requiresIsolation()) {
        SkPaint layer_paint;
        fCtx.modulatePaint(ctm, &layer_paint, /*is_layer_paint = */true);
        fCanvas->saveLayer(bounds, &layer_paint);

        // Fetch the mask shader for restore.
        if (fCtx.fMaskShader) {
            fMaskShader = LocalShader(fCtx.fMaskShader, fCtx.fMaskCTM, ctm);
        }

        // Reset only the props applied via isolation layers.
        fCtx.fColorFilter = nullptr;
        fCtx.fMaskShader  = nullptr;
        fCtx.fOpacity     = 1;
        fCtx.fBlendMode   = SkBlendMode::kSrcOver;
    }

    return std::move(*this);
}

RenderNode::ScopedRenderContext&&
RenderNode::ScopedRenderContext::setFilterIsolation(const SkRect& bounds, const SkMatrix& ctm,
                                                    sk_sp<SkImageFilter> filter) {
    if (filter) {
        SkPaint layer_paint;
        fCtx.modulatePaint(ctm, &layer_paint);

        SkASSERT(!layer_paint.getImageFilter());
        layer_paint.setImageFilter(std::move(filter));
        fCanvas->saveLayer(bounds, &layer_paint);
        fCtx = RenderContext();
    }

    return std::move(*this);
}

CustomRenderNode::CustomRenderNode(std::vector<sk_sp<RenderNode>>&& children)
    : INHERITED(kOverrideDamage_Trait)  // We cannot make any assumptions - override conservatively.
    , fChildren(std::move(children)) {
    for (const auto& child : fChildren) {
        this->observeInval(child);
    }
}

CustomRenderNode::~CustomRenderNode() {
    for (const auto& child : fChildren) {
        this->unobserveInval(child);
    }
}

bool CustomRenderNode::hasChildrenInval() const {
    for (const auto& child : fChildren) {
        if (NodePriv::HasInval(child)) {
            return true;
        }
    }

    return false;
}

} // namespace sksg
