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

#include "modules/svg/include/SkSVGPattern.h"

#include "include/core/SkPaint.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkRect.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkTileMode.h"
#include "modules/svg/include/SkSVGAttributeParser.h"
#include "modules/svg/include/SkSVGContainer.h"
#include "modules/svg/include/SkSVGRenderContext.h"

class SkMatrix;

SkSVGPattern::SkSVGPattern() : INHERITED(SkSVGTag::kPattern) {}

bool SkSVGPattern::parseAndSetAttribute(const char* name, const char* value) {
    return INHERITED::parseAndSetAttribute(name, value) ||
           this->setX(SkSVGAttributeParser::parse<SkSVGLength>("x", name, value)) ||
           this->setY(SkSVGAttributeParser::parse<SkSVGLength>("y", name, value)) ||
           this->setWidth(SkSVGAttributeParser::parse<SkSVGLength>("width", name, value)) ||
           this->setHeight(SkSVGAttributeParser::parse<SkSVGLength>("height", name, value)) ||
           this->setPatternTransform(SkSVGAttributeParser::parse<SkSVGTransformType>(
                   "patternTransform", name, value)) ||
           this->setHref(SkSVGAttributeParser::parse<SkSVGIRI>("xlink:href", name, value));
}

const SkSVGPattern* SkSVGPattern::hrefTarget(const SkSVGRenderContext& ctx) const {
    if (fHref.iri().isEmpty()) {
        return nullptr;
    }

    const auto href = ctx.findNodeById(fHref);
    if (!href || href->tag() != SkSVGTag::kPattern) {
        return nullptr;
    }

    return static_cast<const SkSVGPattern*>(href.get());
}

template <typename T>
int inherit_if_needed(const std::optional<T>& src, std::optional<T>& dst) {
    if (!dst.has_value()) {
        dst = src;
        return 1;
    }

    return 0;
}

/* https://www.w3.org/TR/SVG11/pservers.html#PatternElementHrefAttribute
 *
 * Any attributes which are defined on the referenced element which are not defined on this element
 * are inherited by this element. If this element has no children, and the referenced element does
 * (possibly due to its own ‘xlink:href’ attribute), then this element inherits the children from
 * the referenced element. Inheritance can be indirect to an arbitrary level; thus, if the
 * referenced element inherits attributes or children due to its own ‘xlink:href’ attribute, then
 * the current element can inherit those attributes or children.
 */
const SkSVGPattern* SkSVGPattern::resolveHref(const SkSVGRenderContext& ctx,
                                              PatternAttributes* attrs) const {
    const SkSVGPattern *currentNode = this,
                       *contentNode = this;
    do {
        // Bitwise OR to avoid short-circuiting.
        const bool didInherit =
            inherit_if_needed(currentNode->fX               , attrs->fX)      |
            inherit_if_needed(currentNode->fY               , attrs->fY)      |
            inherit_if_needed(currentNode->fWidth           , attrs->fWidth)  |
            inherit_if_needed(currentNode->fHeight          , attrs->fHeight) |
            inherit_if_needed(currentNode->fPatternTransform, attrs->fPatternTransform);

        if (!contentNode->hasChildren()) {
            contentNode = currentNode;
        }

        if (contentNode->hasChildren() && !didInherit) {
            // All attributes have been resolved, and a valid content node has been found.
            // We can terminate the href chain early.
            break;
        }

        // TODO: reference loop mitigation.
        currentNode = currentNode->hrefTarget(ctx);
    } while (currentNode);

    return contentNode;
}

bool SkSVGPattern::onAsPaint(const SkSVGRenderContext& ctx, SkPaint* paint) const {
    PatternAttributes attrs;
    const auto* contentNode = this->resolveHref(ctx, &attrs);

    const auto tile = ctx.lengthContext().resolveRect(
            attrs.fX.has_value()      ? *attrs.fX      : SkSVGLength(0),
            attrs.fY.has_value()      ? *attrs.fY      : SkSVGLength(0),
            attrs.fWidth.has_value()  ? *attrs.fWidth  : SkSVGLength(0),
            attrs.fHeight.has_value() ? *attrs.fHeight : SkSVGLength(0));

    if (tile.isEmpty()) {
        return false;
    }

    const SkMatrix* patternTransform = SkOptAddressOrNull(attrs.fPatternTransform);

    SkPictureRecorder recorder;
    SkSVGRenderContext recordingContext(ctx, recorder.beginRecording(tile));

    // Cannot call into INHERITED:: because SkSVGHiddenContainer skips rendering.
    contentNode->SkSVGContainer::onRender(recordingContext);

    paint->setShader(recorder.finishRecordingAsPicture()->makeShader(
                                                 SkTileMode::kRepeat,
                                                 SkTileMode::kRepeat,
                                                 SkFilterMode::kLinear,
                                                 patternTransform,
                                                 &tile));
    return true;
}
