/*
 * Copyright (C) 2016-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 "DisplayListRecorder.h"

#include "DisplayList.h"
#include "DisplayListDrawingContext.h"
#include "DisplayListItems.h"
#include "GraphicsContext.h"
#include "ImageBuffer.h"
#include "Logging.h"
#include "MediaPlayer.h"
#include "NotImplemented.h"
#include <wtf/MathExtras.h>
#include <wtf/text/TextStream.h>

namespace WebCore {
namespace DisplayList {

Recorder::Recorder(const GraphicsContextState& state, const FloatRect& initialClip, const AffineTransform& initialCTM, DrawGlyphsRecorder::DeconstructDrawGlyphs deconstructDrawGlyphs)
    : m_drawGlyphsRecorder(*this, deconstructDrawGlyphs)
{
    m_stateStack.append({ state, initialCTM, initialCTM.mapRect(initialClip) });
}

Recorder::Recorder(Recorder& parent, const GraphicsContextState& state, const FloatRect& initialClip, const AffineTransform& initialCTM)
    : m_drawGlyphsRecorder(*this, parent.m_drawGlyphsRecorder.deconstructDrawGlyphs())
{
    m_stateStack.append({ state, initialCTM, initialCTM.mapRect(initialClip) });
}

Recorder::~Recorder()
{
    ASSERT(m_stateStack.size() == 1); // If this fires, it indicates mismatched save/restore.
}

static bool containsOnlyInlineStateChanges(const GraphicsContextStateChange& changes, GraphicsContextState::StateChangeFlags changeFlags)
{
    static constexpr GraphicsContextState::StateChangeFlags inlineStateChangeFlags {
        GraphicsContextState::StrokeThicknessChange,
        GraphicsContextState::StrokeColorChange,
        GraphicsContextState::FillColorChange,
    };

    if (changeFlags != (changeFlags & inlineStateChangeFlags))
        return false;

    if (changeFlags.contains(GraphicsContextState::StrokeColorChange) && !changes.m_state.strokeColor.tryGetAsSRGBABytes())
        return false;

    if (changeFlags.contains(GraphicsContextState::FillColorChange) && !changes.m_state.fillColor.tryGetAsSRGBABytes())
        return false;

    return true;
}

void Recorder::appendStateChangeItem(const GraphicsContextStateChange& changes, GraphicsContextState::StateChangeFlags changeFlags)
{
    if (!containsOnlyInlineStateChanges(changes, changeFlags)) {
        if (auto pattern = changes.m_state.strokePattern)
            recordResourceUse(pattern->tileImage());
        if (auto pattern = changes.m_state.fillPattern)
            recordResourceUse(pattern->tileImage());
        recordSetState(changes.m_state, changeFlags);
        return;
    }

    if (changeFlags.contains(GraphicsContextState::StrokeColorChange))
        recordSetInlineStrokeColor(*changes.m_state.strokeColor.tryGetAsSRGBABytes());

    if (changeFlags.contains(GraphicsContextState::StrokeThicknessChange))
        recordSetStrokeThickness(changes.m_state.strokeThickness);

    if (changeFlags.contains(GraphicsContextState::FillColorChange))
        recordSetInlineFillColor(*changes.m_state.fillColor.tryGetAsSRGBABytes());
}

void Recorder::appendStateChangeItemIfNecessary()
{
    // FIXME: This is currently invoked in an ad-hoc manner when recording drawing items. We should consider either
    // splitting GraphicsContext state changes into individual display list items, or refactoring the code such that
    // this method is automatically invoked when recording a drawing item.
    auto& stateChanges = currentState().stateChange;
    auto changesFromLastState = stateChanges.changesFromState(currentState().lastDrawingState);
    if (!changesFromLastState)
        return;

    LOG_WITH_STREAM(DisplayLists, stream << "pre-drawing, saving state " << GraphicsContextStateChange(stateChanges.m_state, changesFromLastState));
    appendStateChangeItem(stateChanges, changesFromLastState);
    stateChanges.m_changeFlags = { };
    currentState().lastDrawingState = stateChanges.m_state;
}

const GraphicsContextState& Recorder::state() const
{
    return currentState().stateChange.m_state;
}

void Recorder::didUpdateState(const GraphicsContextState& state, GraphicsContextState::StateChangeFlags flags)
{
    currentState().stateChange.accumulate(state, flags);
}

void Recorder::setLineCap(LineCap lineCap)
{
    recordSetLineCap(lineCap);
}

void Recorder::setLineDash(const DashArray& dashArray, float dashOffset)
{
    recordSetLineDash(dashArray, dashOffset);
}

void Recorder::setLineJoin(LineJoin lineJoin)
{
    recordSetLineJoin(lineJoin);
}

void Recorder::setMiterLimit(float miterLimit)
{
    recordSetMiterLimit(miterLimit);
}

void Recorder::drawGlyphs(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
{
    m_drawGlyphsRecorder.drawGlyphs(font, glyphs, advances, numGlyphs, startPoint, smoothingMode);
}

void Recorder::drawGlyphsAndCacheFont(const Font& font, const GlyphBufferGlyph* glyphs, const GlyphBufferAdvance* advances, unsigned count, const FloatPoint& localAnchor, FontSmoothingMode smoothingMode)
{
    appendStateChangeItemIfNecessary();
    recordResourceUse(const_cast<Font&>(font));
    recordDrawGlyphs(font, glyphs, advances, count, localAnchor, smoothingMode);
}

void Recorder::drawImageBuffer(ImageBuffer& imageBuffer, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
    appendStateChangeItemIfNecessary();
    if (!canDrawImageBuffer(imageBuffer)) {
        GraphicsContext::drawImageBuffer(imageBuffer, destRect, srcRect, options);
        return;
    }

    recordResourceUse(imageBuffer);
    recordDrawImageBuffer(imageBuffer.renderingResourceIdentifier(), destRect, srcRect, options);
}

void Recorder::drawNativeImage(NativeImage& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
    appendStateChangeItemIfNecessary();
    recordResourceUse(image);
    recordDrawNativeImage(image.renderingResourceIdentifier(), imageSize, destRect, srcRect, options);
}

void Recorder::drawPattern(NativeImage& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
{
    appendStateChangeItemIfNecessary();
    recordResourceUse(image);
    recordDrawPattern(image.renderingResourceIdentifier(), imageSize, destRect, tileRect, patternTransform, phase, spacing, options);
}

void Recorder::save()
{
    recordSave();
    m_stateStack.append(m_stateStack.last().cloneForSave());
}

void Recorder::restore()
{
    if (!m_stateStack.size())
        return;

    m_stateStack.removeLast();
    recordRestore();
}

void Recorder::translate(float x, float y)
{
    currentState().translate(x, y);
    recordTranslate(x, y);
}

void Recorder::rotate(float angleInRadians)
{
    currentState().rotate(angleInRadians);
    recordRotate(angleInRadians);
}

void Recorder::scale(const FloatSize& size)
{
    currentState().scale(size);
    recordScale(size);
}

void Recorder::concatCTM(const AffineTransform& transform)
{
    if (transform.isIdentity())
        return;

    currentState().concatCTM(transform);
    recordConcatenateCTM(transform);
}

void Recorder::setCTM(const AffineTransform& transform)
{
    currentState().setCTM(transform);
    recordSetCTM(transform);
}

AffineTransform Recorder::getCTM(GraphicsContext::IncludeDeviceScale) const
{
    return currentState().ctm;
}

void Recorder::beginTransparencyLayer(float opacity)
{
    appendStateChangeItemIfNecessary();
    recordBeginTransparencyLayer(opacity);
    m_stateStack.append(m_stateStack.last().cloneForTransparencyLayer());
}

void Recorder::endTransparencyLayer()
{
    appendStateChangeItemIfNecessary();
    recordEndTransparencyLayer();
    m_stateStack.removeLast();
}

void Recorder::drawRect(const FloatRect& rect, float borderThickness)
{
    appendStateChangeItemIfNecessary();
    recordDrawRect(rect, borderThickness);
}

void Recorder::drawLine(const FloatPoint& point1, const FloatPoint& point2)
{
    appendStateChangeItemIfNecessary();
    recordDrawLine(point1, point2);
}

void Recorder::drawLinesForText(const FloatPoint& point, float thickness, const DashArray& widths, bool printing, bool doubleLines, StrokeStyle)
{
    appendStateChangeItemIfNecessary();
    recordDrawLinesForText(FloatPoint(), toFloatSize(point), thickness, widths, printing, doubleLines);
}

void Recorder::drawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle style)
{
    appendStateChangeItemIfNecessary();
    recordDrawDotsForDocumentMarker(rect, style);
}

void Recorder::drawEllipse(const FloatRect& rect)
{
    appendStateChangeItemIfNecessary();
    recordDrawEllipse(rect);
}

void Recorder::drawPath(const Path& path)
{
    appendStateChangeItemIfNecessary();
    recordDrawPath(path);
}

void Recorder::drawFocusRing(const Path& path, float width, float offset, const Color& color)
{
    appendStateChangeItemIfNecessary();
    recordDrawFocusRingPath(path, width, offset, color);
}

void Recorder::drawFocusRing(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
{
    appendStateChangeItemIfNecessary();
    recordDrawFocusRingRects(rects, width, offset, color);
}

#if PLATFORM(MAC)
void Recorder::drawFocusRing(const Path&, double, bool&, const Color&)
{
    notImplemented();
}

void Recorder::drawFocusRing(const Vector<FloatRect>&, double, bool&, const Color&)
{
    notImplemented();
}
#endif

void Recorder::fillRect(const FloatRect& rect)
{
    appendStateChangeItemIfNecessary();
    recordFillRect(rect);
}

void Recorder::fillRect(const FloatRect& rect, const Color& color)
{
    appendStateChangeItemIfNecessary();
    recordFillRectWithColor(rect, color);
}

void Recorder::fillRect(const FloatRect& rect, Gradient& gradient)
{
    appendStateChangeItemIfNecessary();
    recordFillRectWithGradient(rect, gradient);
}

void Recorder::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode blendMode)
{
    appendStateChangeItemIfNecessary();
    recordFillCompositedRect(rect, color, op, blendMode);
}

void Recorder::fillRoundedRect(const FloatRoundedRect& rect, const Color& color, BlendMode blendMode)
{
    appendStateChangeItemIfNecessary();
    recordFillRoundedRect(rect, color, blendMode);
}

void Recorder::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
{
    appendStateChangeItemIfNecessary();
    recordFillRectWithRoundedHole(rect, roundedHoleRect, color);
}

void Recorder::fillPath(const Path& path)
{
    appendStateChangeItemIfNecessary();
#if ENABLE(INLINE_PATH_DATA)
    if (path.hasInlineData()) {
        if (path.hasInlineData<LineData>())
            recordFillLine(path.inlineData<LineData>());
        else if (path.hasInlineData<ArcData>())
            recordFillArc(path.inlineData<ArcData>());
        else if (path.hasInlineData<QuadCurveData>())
            recordFillQuadCurve(path.inlineData<QuadCurveData>());
        else if (path.hasInlineData<BezierCurveData>())
            recordFillBezierCurve(path.inlineData<BezierCurveData>());
        return;
    }
#endif
    recordFillPath(path);
}

void Recorder::fillEllipse(const FloatRect& rect)
{
    appendStateChangeItemIfNecessary();
    recordFillEllipse(rect);
}

void Recorder::strokeRect(const FloatRect& rect, float lineWidth)
{
    appendStateChangeItemIfNecessary();
    recordStrokeRect(rect, lineWidth);
}

void Recorder::strokePath(const Path& path)
{
    appendStateChangeItemIfNecessary();
#if ENABLE(INLINE_PATH_DATA)
    if (path.hasInlineData()) {
        if (path.hasInlineData<LineData>())
            recordStrokeLine(path.inlineData<LineData>());
        else if (path.hasInlineData<ArcData>())
            recordStrokeArc(path.inlineData<ArcData>());
        else if (path.hasInlineData<QuadCurveData>())
            recordStrokeQuadCurve(path.inlineData<QuadCurveData>());
        else if (path.hasInlineData<BezierCurveData>())
            recordStrokeBezierCurve(path.inlineData<BezierCurveData>());
        return;
    }
#endif
    recordStrokePath(path);
}

void Recorder::strokeEllipse(const FloatRect& rect)
{
    appendStateChangeItemIfNecessary();
    recordStrokeEllipse(rect);
}

void Recorder::clearRect(const FloatRect& rect)
{
    appendStateChangeItemIfNecessary();
    recordClearRect(rect);
}

#if USE(CG)
void Recorder::applyStrokePattern()
{
    appendStateChangeItemIfNecessary();
    recordApplyStrokePattern();
}

void Recorder::applyFillPattern()
{
    appendStateChangeItemIfNecessary();
    recordApplyFillPattern();
}
#endif

void Recorder::clip(const FloatRect& rect)
{
    currentState().clipBounds.intersect(currentState().ctm.mapRect(rect));
    recordClip(rect);
}

void Recorder::clipOut(const FloatRect& rect)
{
    recordClipOut(rect);
}

void Recorder::clipOut(const Path& path)
{
    recordClipOutToPath(path);
}

void Recorder::clipPath(const Path& path, WindRule windRule)
{
    currentState().clipBounds.intersect(currentState().ctm.mapRect(path.fastBoundingRect()));
    recordClipPath(path, windRule);
}

IntRect Recorder::clipBounds() const
{
    if (auto inverse = currentState().ctm.inverse())
        return enclosingIntRect(inverse->mapRect(currentState().clipBounds));

    // If the CTM is not invertible, return the original rect.
    // This matches CGRectApplyInverseAffineTransform behavior.
    return enclosingIntRect(currentState().clipBounds);
}

void Recorder::clipToImageBuffer(ImageBuffer& imageBuffer, const FloatRect& destRect)
{
    recordResourceUse(imageBuffer);
    recordClipToImageBuffer(imageBuffer.renderingResourceIdentifier(), destRect);
}

GraphicsContext::ClipToDrawingCommandsResult Recorder::clipToDrawingCommands(const FloatRect& destination, const DestinationColorSpace& colorSpace, Function<void(GraphicsContext&)>&& drawingFunction)
{
    auto initialClip = FloatRect(FloatPoint(), destination.size());

    // The initial CTM matches ImageBuffer's initial CTM.
    AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
    FloatSize scaleFactor(transform.xScale(), transform.yScale());
    auto scaledSize = expandedIntSize(destination.size() * scaleFactor);
    AffineTransform initialCTM;
    initialCTM.scale(1, -1);
    initialCTM.translate(0, -scaledSize.height());
    initialCTM.scale(scaledSize / destination.size());

    auto nestedContext = createNestedContext(initialClip, initialCTM);
    recordBeginClipToDrawingCommands(destination, colorSpace);
    drawingFunction(*nestedContext);
    recordEndClipToDrawingCommands(destination);

    return ClipToDrawingCommandsResult::Success;
}

#if ENABLE(VIDEO)
void Recorder::paintFrameForMedia(MediaPlayer& player, const FloatRect& destination)
{
    if (!player.identifier()) {
        GraphicsContext::paintFrameForMedia(player, destination);
        return;
    }
    ASSERT(player.identifier());
    recordPaintFrameForMedia(player, destination);
}
#endif

void Recorder::applyDeviceScaleFactor(float deviceScaleFactor)
{
    // We modify the state directly here instead of calling GraphicsContext::scale()
    // because the recorded item will scale() when replayed.
    currentState().scale({ deviceScaleFactor, deviceScaleFactor });

    // FIXME: this changes the baseCTM, which will invalidate all of our cached extents.
    // Assert that it's only called early on?
    recordApplyDeviceScaleFactor(deviceScaleFactor);
}

FloatRect Recorder::roundToDevicePixels(const FloatRect& rect, GraphicsContext::RoundingMode)
{
    WTFLogAlways("GraphicsContext::roundToDevicePixels() is not yet compatible with DisplayList::Recorder.");
    return rect;
}

const Recorder::ContextState& Recorder::currentState() const
{
    ASSERT(m_stateStack.size());
    return m_stateStack.last();
}

Recorder::ContextState& Recorder::currentState()
{
    ASSERT(m_stateStack.size());
    return m_stateStack.last();
}

const AffineTransform& Recorder::ctm() const
{
    return currentState().ctm;
}

void Recorder::ContextState::translate(float x, float y)
{
    ctm.translate(x, y);
}

void Recorder::ContextState::rotate(float angleInRadians)
{
    double angleInDegrees = rad2deg(static_cast<double>(angleInRadians));
    ctm.rotate(angleInDegrees);
    
    AffineTransform rotation;
    rotation.rotate(angleInDegrees);
}

void Recorder::ContextState::scale(const FloatSize& size)
{
    ctm.scale(size);
}

void Recorder::ContextState::setCTM(const AffineTransform& matrix)
{
    ctm = matrix;
}

void Recorder::ContextState::concatCTM(const AffineTransform& matrix)
{
    ctm *= matrix;
}

} // namespace DisplayList
} // namespace WebCore
