/*
 * Copyright 2016 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/SkMatrix.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTPin.h"
#include "modules/svg/include/SkSVGNode.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGValue.h"
#include "src/base/SkTLazy.h"

SkSVGNode::SkSVGNode(SkSVGTag t) : fTag(t) {
    // Uninherited presentation attributes need a non-null default value.
    fPresentationAttributes.fStopColor.set(SkSVGColor(SK_ColorBLACK));
    fPresentationAttributes.fStopOpacity.set(SkSVGNumberType(1.0f));
    fPresentationAttributes.fFloodColor.set(SkSVGColor(SK_ColorBLACK));
    fPresentationAttributes.fFloodOpacity.set(SkSVGNumberType(1.0f));
    fPresentationAttributes.fLightingColor.set(SkSVGColor(SK_ColorWHITE));
}

SkSVGNode::~SkSVGNode() { }

void SkSVGNode::render(const SkSVGRenderContext& ctx) const {
    SkSVGRenderContext localContext(ctx, this);

    if (this->onPrepareToRender(&localContext)) {
        this->onRender(localContext);
    }
}

bool SkSVGNode::asPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
    SkSVGRenderContext localContext(ctx);

    return this->onPrepareToRender(&localContext) && this->onAsPaint(localContext, paint);
}

SkPath SkSVGNode::asPath(const SkSVGRenderContext& ctx) const {
    SkSVGRenderContext localContext(ctx);
    if (!this->onPrepareToRender(&localContext)) {
        return SkPath();
    }

    SkPath path = this->onAsPath(localContext);

    if (const auto* clipPath = localContext.clipPath()) {
        // There is a clip-path present on the current node.
        Op(path, *clipPath, kIntersect_SkPathOp, &path);
    }

    return path;
}

SkRect SkSVGNode::objectBoundingBox(const SkSVGRenderContext& ctx) const {
    return this->onObjectBoundingBox(ctx);
}

bool SkSVGNode::onPrepareToRender(SkSVGRenderContext* ctx) const {
    ctx->applyPresentationAttributes(fPresentationAttributes,
                                     this->hasChildren() ? 0 : SkSVGRenderContext::kLeaf);

    // visibility:hidden and display:none disable rendering.
    // TODO: if display is not a value (true when display="inherit"), we currently
    //   ignore it. Eventually we should be able to add SkASSERT(display.isValue()).
    const auto visibility = ctx->presentationContext().fInherited.fVisibility->type();
    const auto display = fPresentationAttributes.fDisplay;  // display is uninherited
    return visibility != SkSVGVisibility::Type::kHidden &&
           (!display.isValue() || *display != SkSVGDisplay::kNone);
}

void SkSVGNode::setAttribute(SkSVGAttribute attr, const SkSVGValue& v) {
    this->onSetAttribute(attr, v);
}

template <typename T>
void SetInheritedByDefault(SkTLazy<T>& presentation_attribute, const T& value) {
    if (value.type() != T::Type::kInherit) {
        presentation_attribute.set(value);
    } else {
        // kInherited values are semantically equivalent to
        // the absence of a local presentation attribute.
        presentation_attribute.reset();
    }
}

bool SkSVGNode::parseAndSetAttribute(const char* n, const char* v) {
#define PARSE_AND_SET(svgName, attrName)                                                        \
    this->set##attrName(                                                                        \
            SkSVGAttributeParser::parseProperty<decltype(fPresentationAttributes.f##attrName)>( \
                    svgName, n, v))

    return PARSE_AND_SET(   "clip-path"                  , ClipPath)
           || PARSE_AND_SET("clip-rule"                  , ClipRule)
           || PARSE_AND_SET("color"                      , Color)
           || PARSE_AND_SET("color-interpolation"        , ColorInterpolation)
           || PARSE_AND_SET("color-interpolation-filters", ColorInterpolationFilters)
           || PARSE_AND_SET("display"                    , Display)
           || PARSE_AND_SET("fill"                       , Fill)
           || PARSE_AND_SET("fill-opacity"               , FillOpacity)
           || PARSE_AND_SET("fill-rule"                  , FillRule)
           || PARSE_AND_SET("filter"                     , Filter)
           || PARSE_AND_SET("flood-color"                , FloodColor)
           || PARSE_AND_SET("flood-opacity"              , FloodOpacity)
           || PARSE_AND_SET("font-family"                , FontFamily)
           || PARSE_AND_SET("font-size"                  , FontSize)
           || PARSE_AND_SET("font-style"                 , FontStyle)
           || PARSE_AND_SET("font-weight"                , FontWeight)
           || PARSE_AND_SET("lighting-color"             , LightingColor)
           || PARSE_AND_SET("mask"                       , Mask)
           || PARSE_AND_SET("opacity"                    , Opacity)
           || PARSE_AND_SET("stop-color"                 , StopColor)
           || PARSE_AND_SET("stop-opacity"               , StopOpacity)
           || PARSE_AND_SET("stroke"                     , Stroke)
           || PARSE_AND_SET("stroke-dasharray"           , StrokeDashArray)
           || PARSE_AND_SET("stroke-dashoffset"          , StrokeDashOffset)
           || PARSE_AND_SET("stroke-linecap"             , StrokeLineCap)
           || PARSE_AND_SET("stroke-linejoin"            , StrokeLineJoin)
           || PARSE_AND_SET("stroke-miterlimit"          , StrokeMiterLimit)
           || PARSE_AND_SET("stroke-opacity"             , StrokeOpacity)
           || PARSE_AND_SET("stroke-width"               , StrokeWidth)
           || PARSE_AND_SET("text-anchor"                , TextAnchor)
           || PARSE_AND_SET("visibility"                 , Visibility);

#undef PARSE_AND_SET
}

// https://www.w3.org/TR/SVG11/coords.html#PreserveAspectRatioAttribute
SkMatrix SkSVGNode::ComputeViewboxMatrix(const SkRect& viewBox,
                                         const SkRect& viewPort,
                                         SkSVGPreserveAspectRatio par) {
    if (viewBox.isEmpty() || viewPort.isEmpty()) {
        return SkMatrix::Scale(0, 0);
    }

    auto compute_scale = [&]() -> SkV2 {
        const auto sx = viewPort.width()  / viewBox.width(),
                   sy = viewPort.height() / viewBox.height();

        if (par.fAlign == SkSVGPreserveAspectRatio::kNone) {
            // none -> anisotropic scaling, regardless of fScale
            return {sx, sy};
        }

        // isotropic scaling
        const auto s = par.fScale == SkSVGPreserveAspectRatio::kMeet
                            ? std::min(sx, sy)
                            : std::max(sx, sy);
        return {s, s};
    };

    auto compute_trans = [&](const SkV2& scale) -> SkV2 {
        static constexpr float gAlignCoeffs[] = {
                0.0f, // Min
                0.5f, // Mid
                1.0f  // Max
        };

        const size_t x_coeff = par.fAlign >> 0 & 0x03,
                     y_coeff = par.fAlign >> 2 & 0x03;

        SkASSERT(x_coeff < std::size(gAlignCoeffs) &&
                 y_coeff < std::size(gAlignCoeffs));

        const auto tx = -viewBox.x() * scale.x,
                   ty = -viewBox.y() * scale.y,
                   dx = viewPort.width()  - viewBox.width() * scale.x,
                   dy = viewPort.height() - viewBox.height() * scale.y;

        return {
            tx + dx * gAlignCoeffs[x_coeff],
            ty + dy * gAlignCoeffs[y_coeff]
        };
    };

    const auto s = compute_scale(),
               t = compute_trans(s);

    return SkMatrix::Translate(t.x, t.y) *
           SkMatrix::Scale(s.x, s.y);
}
