/*
 * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
 *
 * 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 "CanvasStyle.h"

#include "CSSParser.h"
#include "CSSPropertyNames.h"
#include "CanvasGradient.h"
#include "CanvasPattern.h"
#include "ColorConversion.h"
#include "Gradient.h"
#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "StyleProperties.h"

#if ENABLE(OFFSCREEN_CANVAS)
#include "CSSPropertyParserWorkerSafe.h"
#include "OffscreenCanvas.h"
#endif

namespace WebCore {

bool isCurrentColorString(const String& colorString)
{
    return equalLettersIgnoringASCIICase(colorString, "currentcolor"_s);
}

Color parseColor(const String& colorString, CanvasBase& canvasBase)
{
#if ENABLE(OFFSCREEN_CANVAS)
    if (is<OffscreenCanvas>(canvasBase))
        return CSSPropertyParserWorkerSafe::parseColor(colorString);
#endif

    Color color;
    if (is<HTMLCanvasElement>(canvasBase))
        color = CSSParser::parseColor(colorString, CSSParserContext { downcast<HTMLCanvasElement>(canvasBase).document() });
    else
        color = CSSParser::parseColorWithoutContext(colorString);

    if (color.isValid())
        return color;
    return CSSParser::parseSystemColor(colorString);
}

Color currentColor(CanvasBase& canvasBase)
{
    if (!is<HTMLCanvasElement>(canvasBase))
        return Color::black;

    auto& canvas = downcast<HTMLCanvasElement>(canvasBase);
    if (!canvas.isConnected() || !canvas.inlineStyle())
        return Color::black;
    Color color = CSSParser::parseColorWithoutContext(canvas.inlineStyle()->getPropertyValue(CSSPropertyColor));
    if (!color.isValid())
        return Color::black;
    return color;
}

Color parseColorOrCurrentColor(const String& colorString, CanvasBase& canvasBase)
{
    if (isCurrentColorString(colorString))
        return currentColor(canvasBase);

    return parseColor(colorString, canvasBase);
}

CanvasStyle::CanvasStyle(Color color)
    : m_style(color)
{
}

CanvasStyle::CanvasStyle(const SRGBA<float>& colorComponents)
    : m_style(convertColor<SRGBA<uint8_t>>(colorComponents))
{
}

CanvasStyle::CanvasStyle(CanvasGradient& gradient)
    : m_style(&gradient)
{
}

CanvasStyle::CanvasStyle(CanvasPattern& pattern)
    : m_style(&pattern)
{
}

inline CanvasStyle::CanvasStyle(CurrentColor color)
    : m_style(color)
{
}

CanvasStyle CanvasStyle::createFromString(const String& colorString, CanvasBase& canvasBase)
{
    if (isCurrentColorString(colorString))
        return CurrentColor { std::nullopt };

    Color color = parseColor(colorString, canvasBase);
    if (!color.isValid())
        return { };

    return color;
}

CanvasStyle CanvasStyle::createFromStringWithOverrideAlpha(const String& colorString, float alpha, CanvasBase& canvasBase)
{
    if (isCurrentColorString(colorString))
        return CurrentColor { alpha };

    Color color = parseColor(colorString, canvasBase);
    if (!color.isValid())
        return { };

    return color.colorWithAlpha(alpha);
}

bool CanvasStyle::isEquivalentColor(const CanvasStyle& other) const
{
    if (std::holds_alternative<Color>(m_style) && std::holds_alternative<Color>(other.m_style))
        return std::get<Color>(m_style) == std::get<Color>(other.m_style);

    return false;
}

bool CanvasStyle::isEquivalent(const SRGBA<float>& components) const
{
    return std::holds_alternative<Color>(m_style) && std::get<Color>(m_style) == convertColor<SRGBA<uint8_t>>(components);
}

void CanvasStyle::applyStrokeColor(GraphicsContext& context) const
{
    WTF::switchOn(m_style,
        [&context] (const Color& color) {
            context.setStrokeColor(color);
        },
        [&context] (const RefPtr<CanvasGradient>& gradient) {
            context.setStrokeGradient(gradient->gradient());
        },
        [&context] (const RefPtr<CanvasPattern>& pattern) {
            context.setStrokePattern(pattern->pattern());
        },
        [] (const CurrentColor&) {
            ASSERT_NOT_REACHED();
        },
        [] (const Invalid&) {
            ASSERT_NOT_REACHED();
        }
    );
}

void CanvasStyle::applyFillColor(GraphicsContext& context) const
{
    WTF::switchOn(m_style,
        [&context] (const Color& color) {
            context.setFillColor(color);
        },
        [&context] (const RefPtr<CanvasGradient>& gradient) {
            context.setFillGradient(gradient->gradient());
        },
        [&context] (const RefPtr<CanvasPattern>& pattern) {
            context.setFillPattern(pattern->pattern());
        },
        [] (const CurrentColor&) {
            ASSERT_NOT_REACHED();
        },
        [] (const Invalid&) {
            ASSERT_NOT_REACHED();
        }
    );
}

}
