/*
 * Copyright (C) 2019-2021 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 "PlatformContextDirect2D.h"

#if USE(DIRECT2D)

#include "Direct2DOperations.h"
#include "Direct2DUtilities.h"
#include <d2d1.h>

namespace WebCore {

// Encapsulates the additional painting state information we store for each
// pushed graphics state.
class PlatformContextDirect2D::State {
public:
    State() = default;

    COMPtr<ID2D1DrawingStateBlock> m_drawingStateBlock;
    COMPtr<ID2D1Layer> m_activeLayer;
    Vector<Direct2DLayerType> m_clips;
};

PlatformContextDirect2D::PlatformContextDirect2D(ID2D1RenderTarget* renderTarget, Function<void()>&& preDrawHandler, Function<void()>&& postDrawHandler)
    : m_renderTarget(renderTarget)
    , m_preDrawHandler(WTFMove(preDrawHandler))
    , m_postDrawHandler(WTFMove(postDrawHandler))
{
    m_stateStack.append(State());
    m_state = &m_stateStack.last();

    m_deviceContext.query(m_renderTarget.get());
    RELEASE_ASSERT(!!m_deviceContext);
}

void PlatformContextDirect2D::setRenderTarget(ID2D1RenderTarget* renderTarget)
{
    m_renderTarget = renderTarget;

    m_deviceContext.query(m_renderTarget.get());
    RELEASE_ASSERT(!!m_deviceContext);
}

ID2D1Layer* PlatformContextDirect2D::clipLayer() const
{
    return m_state->m_activeLayer.get();
}

void PlatformContextDirect2D::clearClips(Vector<Direct2DLayerType>& clips)
{
    for (auto clipType = clips.rbegin(); clipType != clips.rend(); ++clipType) {
        if (*clipType == AxisAlignedClip)
            m_renderTarget->PopAxisAlignedClip();
        else
            m_renderTarget->PopLayer();
    }

    clips.clear();
}

void PlatformContextDirect2D::restore()
{
    ASSERT(m_renderTarget);

    // No need to restore if we don't have a saved element on the stack.
    if (m_stateStack.size() == 1)
        return;

    auto& restoreState = m_stateStack.last();
    if (restoreState.m_drawingStateBlock) {
        m_renderTarget->RestoreDrawingState(restoreState.m_drawingStateBlock.get());
        restoreState.m_drawingStateBlock = nullptr;
    }

    clearClips(restoreState.m_clips);

    m_stateStack.removeLast();
    ASSERT(!m_stateStack.isEmpty());
    m_state = &m_stateStack.last();
}

PlatformContextDirect2D::~PlatformContextDirect2D() = default;

void PlatformContextDirect2D::save()
{
    ASSERT(m_stateStack.size() >= 1); // There should always be one state on the stack.
    ASSERT(m_renderTarget);

    m_stateStack.append(State());
    m_state = &m_stateStack.last();

    GraphicsContext::systemFactory()->CreateDrawingStateBlock(&m_state->m_drawingStateBlock);

    m_renderTarget->SaveDrawingState(m_state->m_drawingStateBlock.get());
}

void PlatformContextDirect2D::pushRenderClip(Direct2DLayerType clipType)
{
    ASSERT(hasSavedState());
    m_state->m_clips.append(clipType);
}

void PlatformContextDirect2D::setActiveLayer(COMPtr<ID2D1Layer>&& layer)
{
    ASSERT(hasSavedState());
    m_state->m_activeLayer = layer;
}

COMPtr<ID2D1SolidColorBrush> PlatformContextDirect2D::brushWithColor(const D2D1_COLOR_F& color)
{
    auto colorKey = colorConvert<SRGBA<uint8_t>>(SRGBA<float> { color.r, color.g, color.b, color.a });

    if (!colorKey) {
        if (!m_zeroBrush)
            m_renderTarget->CreateSolidColorBrush(color, &m_zeroBrush);
        return m_zeroBrush;
    }

    if (colorKey == 0xFFFFFFFF) {
        if (!m_whiteBrush)
            m_renderTarget->CreateSolidColorBrush(color, &m_whiteBrush);
        return m_whiteBrush;
    }

    auto existingBrush = m_solidColoredBrushCache.ensure(colorKey, [this, color] {
        COMPtr<ID2D1SolidColorBrush> colorBrush;
        m_renderTarget->CreateSolidColorBrush(color, &colorBrush);
        return colorBrush;
    });

    return existingBrush.iterator->value;
}

void PlatformContextDirect2D::recomputeStrokeStyle()
{
    if (!m_strokeSyleIsDirty)
        return;

    m_d2dStrokeStyle = nullptr;

    DashArray dashes;
    float patternOffset = 0;
    auto dashStyle = D2D1_DASH_STYLE_SOLID;

    if ((m_strokeStyle != SolidStroke) && (m_strokeStyle != NoStroke)) {
        dashStyle = D2D1_DASH_STYLE_CUSTOM;
        patternOffset = m_patternOffset / m_strokeThickness;
        dashes = m_dashes;

        // In Direct2D, dashes and dots are defined in terms of the ratio of the dash length to the line thickness.
        for (auto& dash : dashes)
            dash /= m_strokeThickness;
    }

    auto strokeStyleProperties = D2D1::StrokeStyleProperties(m_lineCap, m_lineCap, m_lineCap, m_lineJoin, m_miterLimit, dashStyle, patternOffset);
    GraphicsContext::systemFactory()->CreateStrokeStyle(&strokeStyleProperties, dashes.data(), dashes.size(), &m_d2dStrokeStyle);

    m_strokeSyleIsDirty = false;
}

ID2D1StrokeStyle* PlatformContextDirect2D::strokeStyle()
{
    recomputeStrokeStyle();
    return m_d2dStrokeStyle.get();
}

D2D1_STROKE_STYLE_PROPERTIES PlatformContextDirect2D::strokeStyleProperties() const
{
    return D2D1::StrokeStyleProperties(m_lineCap, m_lineCap, m_lineCap, m_lineJoin, m_miterLimit, D2D1_DASH_STYLE_SOLID, 0.0f);
}

void PlatformContextDirect2D::setLineCap(D2D1_CAP_STYLE lineCap)
{
    if (m_lineCap == lineCap)
        return;

    m_lineCap = lineCap;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setLineJoin(D2D1_LINE_JOIN join)
{
    if (m_lineJoin == join)
        return;

    m_lineJoin = join;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setStrokeStyle(StrokeStyle strokeStyle)
{
    if (m_strokeStyle == strokeStyle)
        return;

    m_strokeStyle = strokeStyle;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setStrokeThickness(float thickness)
{
    if (WTF::areEssentiallyEqual(thickness, m_strokeThickness))
        return;

    m_strokeThickness = thickness;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setMiterLimit(float canvasMiterLimit)
{
    // Direct2D miter limit is in terms of HALF the line thickness.
    float miterLimit = 0.5f * canvasMiterLimit;
    if (WTF::areEssentiallyEqual(miterLimit, m_miterLimit))
        return;

    m_miterLimit = miterLimit;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setDashOffset(float dashOffset)
{
    if (WTF::areEssentiallyEqual(dashOffset, m_dashOffset))
        return;

    m_dashOffset = dashOffset;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setDashes(const DashArray& dashes)
{
    if (m_dashes == dashes)
        return;

    m_dashes = dashes;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setPatternWidth(float patternWidth)
{
    if (WTF::areEssentiallyEqual(patternWidth, m_patternWidth))
        return;

    m_patternWidth = patternWidth;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::setPatternOffset(float patternOffset)
{
    if (WTF::areEssentiallyEqual(patternOffset, m_patternOffset))
        return;

    m_patternOffset = patternOffset;
    m_strokeSyleIsDirty = true;
}

void PlatformContextDirect2D::beginDraw()
{
    ASSERT(m_renderTarget);
    m_renderTarget->BeginDraw();
    ++beginDrawCount;
}

void PlatformContextDirect2D::endDraw()
{
    ASSERT(m_renderTarget);

    if (m_stateStack.size() > 1)
        restore();

    clearClips(m_state->m_clips);

    ASSERT(m_stateStack.size() >= 1);

    D2D1_TAG first, second;
    HRESULT hr = m_renderTarget->EndDraw(&first, &second);

    if (!SUCCEEDED(hr))
        WTFLogAlways("Failed in PlatformContextDirect2D::endDraw: hr=%xd, first=%ld, second=%ld", hr, first, second);

    --beginDrawCount;

    compositeIfNeeded();
}

void PlatformContextDirect2D::setTags(D2D1_TAG tag1, D2D1_TAG tag2)
{
#if ASSERT_ENABLED
    m_renderTarget->SetTags(tag1, tag2);
#else
    UNUSED_PARAM(tag1);
    UNUSED_PARAM(tag2);
#endif
}

void PlatformContextDirect2D::notifyPreDrawObserver()
{
    m_preDrawHandler();
}

void PlatformContextDirect2D::notifyPostDrawObserver()
{
    m_postDrawHandler();
}

void PlatformContextDirect2D::pushClip(Direct2DLayerType clipType)
{
    m_state->m_clips.append(clipType);
}

void PlatformContextDirect2D::compositeIfNeeded()
{
    if (!m_compositeSource)
        return;

    COMPtr<ID2D1BitmapRenderTarget> bitmapTarget(Query, m_renderTarget.get());
    if (!bitmapTarget)
        return;

    COMPtr<ID2D1Bitmap> currentCanvas = Direct2D::createBitmapCopyFromContext(bitmapTarget.get());
    if (!currentCanvas)
        return;

    COMPtr<ID2D1Effect> effect;

    if (m_compositeMode != D2D1_COMPOSITE_MODE_FORCE_DWORD) {
        m_deviceContext->CreateEffect(CLSID_D2D1Composite, &effect);
        effect->SetInput(0, m_compositeSource.get());
        effect->SetInput(1, currentCanvas.get());
        effect->SetValue(D2D1_COMPOSITE_PROP_MODE, m_compositeMode);
    } else if (m_blendMode != D2D1_BLEND_MODE_FORCE_DWORD) {
        m_deviceContext->CreateEffect(CLSID_D2D1Blend, &effect);
        effect->SetInput(0, currentCanvas.get());
        effect->SetInput(1, m_compositeSource.get());
        effect->SetValue(D2D1_BLEND_PROP_MODE, m_blendMode);
    }

    if (effect) {
        m_deviceContext->BeginDraw();
        m_deviceContext->Clear(D2D1::ColorF(0, 0, 0, 0));
        m_deviceContext->DrawImage(effect.get());
        m_deviceContext->EndDraw();
    }

    m_compositeSource = nullptr;
}

void PlatformContextDirect2D::setBlendAndCompositeMode(D2D1_BLEND_MODE blend, D2D1_COMPOSITE_MODE mode)
{
    if (mode == m_compositeMode && blend == m_blendMode)
        return;

    // Direct2D handles compositing based on bitmaps. If we are changing the
    // compositing mode, we need to capture the current state of the rendering
    // in a bitmap, perform drawing operations until we finish, then handle
    // the composting of the two layers.
    COMPtr<ID2D1BitmapRenderTarget> bitmapTarget(Query, m_renderTarget.get());
    if (!bitmapTarget)
        return;

    endDraw();

    m_compositeMode = mode;
    m_blendMode = blend;

    m_compositeSource = Direct2D::createBitmapCopyFromContext(bitmapTarget.get());

    beginDraw();

    m_deviceContext->Clear(D2D1::ColorF(0, 0, 0, 0));
}

} // namespace WebCore

#endif // USE(DIRECT2D)
