/*
 * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "CSSFilter.h"

#include "FEColorMatrix.h"
#include "FEComponentTransfer.h"
#include "FEDropShadow.h"
#include "FEGaussianBlur.h"
#include "FEMerge.h"
#include "FilterOperations.h"
#include "GraphicsContext.h"
#include "LengthFunctions.h"
#include "Logging.h"
#include "ReferencedSVGResources.h"
#include "RenderElement.h"
#include "SVGFilter.h"
#include "SVGFilterBuilder.h"
#include "SVGFilterElement.h"
#include "SourceGraphic.h"

#if USE(DIRECT2D)
#include <d2d1.h>
#endif

namespace WebCore {

RefPtr<CSSFilter> CSSFilter::create(const FilterOperations& operations, RenderingMode renderingMode, float scaleFactor)
{
    bool hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
    bool hasFilterThatShouldBeRestrictedBySecurityOrigin = operations.hasFilterThatShouldBeRestrictedBySecurityOrigin();

    return adoptRef(*new CSSFilter(renderingMode, scaleFactor, hasFilterThatMovesPixels, hasFilterThatShouldBeRestrictedBySecurityOrigin));
}

CSSFilter::CSSFilter(RenderingMode renderingMode, float scaleFactor, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin)
    : Filter(Filter::Type::CSSFilter, renderingMode, FloatSize { scaleFactor, scaleFactor })
    , m_hasFilterThatMovesPixels(hasFilterThatMovesPixels)
    , m_hasFilterThatShouldBeRestrictedBySecurityOrigin(hasFilterThatShouldBeRestrictedBySecurityOrigin)
{
}

static RefPtr<FilterEffect> createBlurEffect(const BlurFilterOperation& blurOperation, FilterConsumer consumer)
{
    float stdDeviation = floatValueForLength(blurOperation.stdDeviation(), 0);
    return FEGaussianBlur::create(stdDeviation, stdDeviation, consumer == FilterConsumer::FilterProperty ? EdgeModeType::None : EdgeModeType::Duplicate);
}

static RefPtr<FilterEffect> createBrightnessEffect(const BasicComponentTransferFilterOperation& componentTransferOperation)
{
    ComponentTransferFunction transferFunction;
    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation.amount());
    transferFunction.intercept = 0;

    ComponentTransferFunction nullFunction;
    return FEComponentTransfer::create(transferFunction, transferFunction, transferFunction, nullFunction);
}

static RefPtr<FilterEffect> createContrastEffect(const BasicComponentTransferFilterOperation& componentTransferOperation)
{
    ComponentTransferFunction transferFunction;
    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    transferFunction.slope = amount;
    transferFunction.intercept = -0.5 * amount + 0.5;

    ComponentTransferFunction nullFunction;
    return FEComponentTransfer::create(transferFunction, transferFunction, transferFunction, nullFunction);
}

static RefPtr<FilterEffect> createDropShadowEffect(const DropShadowFilterOperation& dropShadowOperation)
{
    float std = dropShadowOperation.stdDeviation();
    return FEDropShadow::create(std, std, dropShadowOperation.x(), dropShadowOperation.y(), dropShadowOperation.color(), 1);
}

static RefPtr<FilterEffect> createGrayScaleEffect(const BasicColorMatrixFilterOperation& colorMatrixOperation)
{
    double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);

    // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
    // for information on parameters.

    Vector<float> inputParameters {
        narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount),
        narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
        narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
        0,
        0,

        narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
        narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount),
        narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
        0,
        0,

        narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
        narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
        narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount),
        0,
        0,

        0,
        0,
        0,
        1,
        0,
    };

    return FEColorMatrix::create(FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
}

static RefPtr<FilterEffect> createHueRotateEffect(const BasicColorMatrixFilterOperation& colorMatrixOperation)
{
    Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
    return FEColorMatrix::create(FECOLORMATRIX_TYPE_HUEROTATE, WTFMove(inputParameters));
}

static RefPtr<FilterEffect> createInvertEffect(const BasicComponentTransferFilterOperation& componentTransferOperation)
{
    ComponentTransferFunction transferFunction;
    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    transferFunction.slope = 1 - 2 * amount;
    transferFunction.intercept = amount;

    ComponentTransferFunction nullFunction;
    return FEComponentTransfer::create(transferFunction, transferFunction, transferFunction, nullFunction);
}

static RefPtr<FilterEffect> createOpacityEffect(const BasicComponentTransferFilterOperation& componentTransferOperation)
{
    ComponentTransferFunction transferFunction;
    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    transferFunction.slope = amount;
    transferFunction.intercept = 0;

    ComponentTransferFunction nullFunction;
    return FEComponentTransfer::create(nullFunction, nullFunction, nullFunction, transferFunction);
}

static RefPtr<FilterEffect> createSaturateEffect(const BasicColorMatrixFilterOperation& colorMatrixOperation)
{
    Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
    return FEColorMatrix::create(FECOLORMATRIX_TYPE_SATURATE, WTFMove(inputParameters));
}

static RefPtr<FilterEffect> createSepiaEffect(const BasicColorMatrixFilterOperation& colorMatrixOperation)
{
    double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);

    // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
    // for information on parameters.

    Vector<float> inputParameters {
        narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount),
        narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount),
        narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount),
        0,
        0,

        narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount),
        narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount),
        narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount),
        0,
        0,

        narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount),
        narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount),
        narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount),
        0,
        0,

        0,
        0,
        0,
        1,
        0,
    };

    return FEColorMatrix::create(FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
}

static RefPtr<SVGFilter> createSVGFilter(CSSFilter& filter, const ReferenceFilterOperation& filterOperation, RenderElement& renderer, FilterEffect& previousEffect)
{
    auto& referencedSVGResources = renderer.ensureReferencedSVGResources();
    auto* filterElement = referencedSVGResources.referencedFilterElement(renderer.document(), filterOperation);

    if (!filterElement) {
        LOG_WITH_STREAM(Filters, stream << " buildReferenceFilter: failed to find filter renderer, adding pending resource " << filterOperation.fragment());
        // Although we did not find the referenced filter, it might exist later in the document.
        // FIXME: This skips anonymous RenderObjects. <https://webkit.org/b/131085>
        // FIXME: Unclear if this does anything.
        return nullptr;
    }

    SVGFilterBuilder builder;
    return SVGFilter::create(*filterElement, builder, filter.renderingMode(), filter.filterScale(), filter.sourceImageRect(), filter.filterRegion(), previousEffect);
}

static void setupLastEffectProperties(FilterEffect& effect, FilterConsumer consumer)
{
    // Unlike SVG Filters and CSSFilterImages, filter functions on the filter
    // property applied here should not clip to their primitive subregions.
    effect.setClipsToBounds(consumer == FilterConsumer::FilterFunction);
    effect.setOperatingColorSpace(DestinationColorSpace::SRGB());
}

bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperations& operations, FilterConsumer consumer)
{
    m_functions.clear();
    m_outsets = { };

    RefPtr<FilterEffect> previousEffect = SourceGraphic::create();
    RefPtr<SVGFilter> filter;
    
    for (auto& operation : operations.operations()) {
        RefPtr<FilterEffect> effect;

        switch (operation->type()) {
        case FilterOperation::APPLE_INVERT_LIGHTNESS:
            ASSERT_NOT_REACHED(); // APPLE_INVERT_LIGHTNESS is only used in -apple-color-filter.
            break;

        case FilterOperation::BLUR:
            effect = createBlurEffect(downcast<BlurFilterOperation>(*operation), consumer);
            break;

        case FilterOperation::BRIGHTNESS:
            effect = createBrightnessEffect(downcast<BasicComponentTransferFilterOperation>(*operation));
            break;

        case FilterOperation::CONTRAST:
            effect = createContrastEffect(downcast<BasicComponentTransferFilterOperation>(*operation));
            break;

        case FilterOperation::DROP_SHADOW:
            effect = createDropShadowEffect(downcast<DropShadowFilterOperation>(*operation));
            break;

        case FilterOperation::GRAYSCALE:
            effect = createGrayScaleEffect(downcast<BasicColorMatrixFilterOperation>(*operation));
            break;

        case FilterOperation::HUE_ROTATE:
            effect = createHueRotateEffect(downcast<BasicColorMatrixFilterOperation>(*operation));
            break;

        case FilterOperation::INVERT:
            effect = createInvertEffect(downcast<BasicComponentTransferFilterOperation>(*operation));
            break;

        case FilterOperation::OPACITY:
            effect = createOpacityEffect(downcast<BasicComponentTransferFilterOperation>(*operation));
            break;

        case FilterOperation::SATURATE:
            effect = createSaturateEffect(downcast<BasicColorMatrixFilterOperation>(*operation));
            break;

        case FilterOperation::SEPIA:
            effect = createSepiaEffect(downcast<BasicColorMatrixFilterOperation>(*operation));
            break;

        case FilterOperation::REFERENCE:
            filter = createSVGFilter(*this, downcast<ReferenceFilterOperation>(*operation), renderer, *previousEffect);
            effect = nullptr;
            break;

        default:
            break;
        }

        if ((filter || effect) && m_functions.isEmpty()) {
            ASSERT(previousEffect->filterType() == FilterEffect::Type::SourceGraphic);
            m_functions.append({ *previousEffect });
        }
        
        if (filter) {
            effect = filter->lastEffect();
            setupLastEffectProperties(*effect, consumer);
            m_functions.append(filter.releaseNonNull());
            previousEffect = WTFMove(effect);
            continue;
        }

        if (effect) {
            setupLastEffectProperties(*effect, consumer);
            effect->inputEffects() = { WTFMove(previousEffect) };
            m_functions.append({ *effect });
            previousEffect = WTFMove(effect);
        }
    }

    // If we didn't make any effects, tell our caller we are not valid.
    if (m_functions.isEmpty())
        return false;

    m_functions.shrinkToFit();

#if USE(CORE_IMAGE)
    if (!supportsCoreImageRendering())
        setRenderingMode(RenderingMode::Unaccelerated);
#endif

    return true;
}

GraphicsContext* CSSFilter::inputContext()
{
    return sourceImage() ? &sourceImage()->context() : nullptr;
}

bool CSSFilter::updateBackingStoreRect(const FloatRect& filterRect)
{
    if (filterRect.isEmpty() || ImageBuffer::sizeNeedsClamping(filterRect.size()))
        return false;

    if (filterRect == sourceImageRect())
        return false;

    setSourceImageRect(filterRect);
    return true;
}

void CSSFilter::allocateBackingStoreIfNeeded(const GraphicsContext& targetContext)
{
    // At this point the effect chain has been built, and the
    // source image sizes set. We just need to attach the graphic
    // buffer if we have not yet done so.

    if (m_graphicsBufferAttached)
        return;

    auto logicalSize = sourceImageRect().size();
    if (!sourceImage() || sourceImage()->logicalSize() != logicalSize) {
#if USE(DIRECT2D)
        setSourceImage(ImageBuffer::create(logicalSize, renderingMode(), &targetContext, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8));
#else
        UNUSED_PARAM(targetContext);
        setSourceImage(ImageBuffer::create(logicalSize, renderingMode(), 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8));
#endif
        if (auto context = inputContext())
            context->scale(filterScale());
    }

    m_graphicsBufferAttached = true;
}

RefPtr<FilterEffect> CSSFilter::lastEffect()
{
    if (m_functions.isEmpty())
        return nullptr;

    auto& function = m_functions.last();
    if (function->isSVGFilter())
        return downcast<SVGFilter>(function.ptr())->lastEffect();

    return downcast<FilterEffect>(function.ptr());
}

#if USE(CORE_IMAGE)
bool CSSFilter::supportsCoreImageRendering() const
{
    if (renderingMode() == RenderingMode::Unaccelerated)
        return false;

    for (auto& function : m_functions) {
        if (!function->supportsCoreImageRendering())
            return false;
    }

    return true;
}
#endif

void CSSFilter::determineFilterPrimitiveSubregion()
{
    auto effect = lastEffect();
    effect->determineFilterPrimitiveSubregion(*this);
    FloatRect subRegion = effect->maxEffectRect();
    // At least one FilterEffect has a too big image size, recalculate the effect sizes with new scale factors.
    FloatSize filterScale { 1, 1 };
    if (ImageBuffer::sizeNeedsClamping(subRegion.size(), filterScale)) {
        setFilterScale(filterScale);
        effect->determineFilterPrimitiveSubregion(*this);
    }
}

void CSSFilter::clearIntermediateResults()
{
    for (auto& function : m_functions)
        function->clearResult();
}

bool CSSFilter::apply()
{
    for (auto& function : m_functions) {
        if (!function->apply(*this))
            return false;
    }

    lastEffect()->transformResultColorSpace(DestinationColorSpace::SRGB());
    return true;
}

LayoutRect CSSFilter::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
{
    // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
    auto rectForRepaint = dirtyRect;
    if (hasFilterThatMovesPixels())
        rectForRepaint += outsets();
    rectForRepaint.intersect(filterBoxRect);
    return rectForRepaint;
}

ImageBuffer* CSSFilter::output()
{
    if (auto result = lastEffect()->filterImage())
        return result->imageBuffer();

    return nullptr;
}

void CSSFilter::setSourceImageRect(const FloatRect& sourceImageRect)
{
    auto scaledSourceImageRect = sourceImageRect;
    scaledSourceImageRect.scale(filterScale());

    Filter::setFilterRegion(sourceImageRect);
    Filter::setSourceImageRect(scaledSourceImageRect);

    for (auto& function : m_functions) {
        if (function->isSVGFilter()) {
            downcast<SVGFilter>(function.ptr())->setFilterRegion(sourceImageRect);
            downcast<SVGFilter>(function.ptr())->setSourceImageRect(scaledSourceImageRect);
        }
    }

    m_graphicsBufferAttached = false;
}

IntRect CSSFilter::outputRect()
{
    auto effect = lastEffect();

    if (auto result = effect->filterImage())
        return result->absoluteImageRect() - IntPoint(filterRegion().location());

    return { };
}

IntOutsets CSSFilter::outsets() const
{
    if (!m_hasFilterThatMovesPixels)
        return { };

    if (!m_outsets.isZero())
        return m_outsets;

    for (auto& function : m_functions)
        m_outsets += function->outsets();
    return m_outsets;
}

} // namespace WebCore
