/*
 * Copyright (C) 2011-2017 Apple 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 "FilterOperations.h"

#include "ColorUtilities.h"
#include "FEGaussianBlur.h"
#include "IntSize.h"
#include "LengthFunctions.h"
#include <wtf/text/TextStream.h>

namespace WebCore {

static inline IntSize outsetSizeForBlur(float stdDeviation)
{
    auto kernelSize = FEGaussianBlur::calculateUnscaledKernelSize({ stdDeviation, stdDeviation });

    // We take the half kernel size and multiply it with three, because we run box blur three times.
    return {
        3 * kernelSize.width() / 2,
        3 * kernelSize.height() / 2
    };
}

bool FilterOperations::operator==(const FilterOperations& other) const
{
    size_t size = m_operations.size();
    if (size != other.m_operations.size())
        return false;
    for (size_t i = 0; i < size; i++) {
        if (*m_operations[i] != *other.m_operations[i])
            return false;
    }
    return true;
}

bool FilterOperations::operationsMatch(const FilterOperations& other) const
{
    size_t size = operations().size();
    if (size != other.operations().size())
        return false;
    for (size_t i = 0; i < size; ++i) {
        if (!operations()[i]->isSameType(*other.operations()[i]))
            return false;
    }
    return true;
}

bool FilterOperations::hasReferenceFilter() const
{
    for (auto& operation : m_operations) {
        if (operation->type() == FilterOperation::REFERENCE)
            return true;
    }
    return false;
}

bool FilterOperations::hasOutsets() const
{
    for (auto& operation : m_operations) {
        auto type = operation->type();
        if (type == FilterOperation::BLUR || type == FilterOperation::DROP_SHADOW)
            return true;
    }
    return false;
}

FilterOutsets FilterOperations::outsets() const
{
    FilterOutsets totalOutsets;
    for (auto& operation : m_operations) {
        switch (operation->type()) {
        case FilterOperation::BLUR: {
            auto& blurOperation = downcast<BlurFilterOperation>(*operation);
            float stdDeviation = floatValueForLength(blurOperation.stdDeviation(), 0);
            IntSize outsetSize = outsetSizeForBlur(stdDeviation);
            FilterOutsets outsets(outsetSize.height(), outsetSize.width(), outsetSize.height(), outsetSize.width());
            totalOutsets += outsets;
            break;
        }
        case FilterOperation::DROP_SHADOW: {
            auto& dropShadowOperation = downcast<DropShadowFilterOperation>(*operation);
            IntSize outsetSize = outsetSizeForBlur(dropShadowOperation.stdDeviation());
            FilterOutsets outsets {
                std::max(0, outsetSize.height() - dropShadowOperation.y()),
                std::max(0, outsetSize.width() + dropShadowOperation.x()),
                std::max(0, outsetSize.height() + dropShadowOperation.y()),
                std::max(0, outsetSize.width() - dropShadowOperation.x())
            };
            totalOutsets += outsets;
            break;
        }
        default:
            break;
        }
    }
    return totalOutsets;
}

bool FilterOperations::transformColor(Color& color) const
{
    if (isEmpty())
        return false;

    FloatComponents components;
    color.getRGBA(components.components[0], components.components[1], components.components[2], components.components[3]);

    for (auto& operation : m_operations) {
        if (!operation->transformColor(components))
            return false;
    }

    color = Color(components.components[0], components.components[1], components.components[2], components.components[3]);
    return true;
}

bool FilterOperations::hasFilterThatAffectsOpacity() const
{
    for (auto& operation : m_operations) {
        if (operation->affectsOpacity())
            return true;
    }
    return false;
}

bool FilterOperations::hasFilterThatMovesPixels() const
{
    for (auto& operation : m_operations) {
        if (operation->movesPixels())
            return true;
    }
    return false;
}

bool FilterOperations::hasFilterThatShouldBeRestrictedBySecurityOrigin() const
{
    for (auto& operation : m_operations) {
        if (operation->shouldBeRestrictedBySecurityOrigin())
            return true;
    }
    return false;
}

TextStream& operator<<(TextStream& ts, const FilterOperations& filters)
{
    for (size_t i = 0; i < filters.size(); ++i) {
        auto filter = filters.at(i);
        if (filter)
            ts << *filter;
        else
            ts << "(null)";
        if (i < filters.size() - 1)
            ts << " ";
    }
    return ts;
}

} // namespace WebCore
