/*
 * Copyright (C) 2016 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 "DisplayListItems.h"
#include "GraphicsContext.h"
#include "Logging.h"
#include <wtf/MathExtras.h>
#include <wtf/text/TextStream.h>

namespace WebCore {
namespace DisplayList {

Recorder::Recorder(GraphicsContext& context, DisplayList& displayList, const GraphicsContextState& state, const FloatRect& initialClip, const AffineTransform& baseCTM)
    : GraphicsContextImpl(context, initialClip, baseCTM)
    , m_displayList(displayList)
{
    LOG_WITH_STREAM(DisplayLists, stream << "\nRecording with clip " << initialClip);
    m_stateStack.append(ContextState(state, baseCTM, initialClip));
}

Recorder::~Recorder()
{
    ASSERT(m_stateStack.size() == 1); // If this fires, it indicates mismatched save/restore.
    LOG(DisplayLists, "Recorded display list:\n%s", m_displayList.description().data());
}

void Recorder::willAppendItem(const Item& item)
{
    if (item.isDrawingItem()
#if USE(CG)
        || item.type() == ItemType::ApplyStrokePattern || item.type() == ItemType::ApplyStrokePattern
#endif
    ) {
        GraphicsContextStateChange& stateChanges = currentState().stateChange;
        GraphicsContextState::StateChangeFlags changesFromLastState = stateChanges.changesFromState(currentState().lastDrawingState);
        if (changesFromLastState) {
            LOG_WITH_STREAM(DisplayLists, stream << "pre-drawing, saving state " << GraphicsContextStateChange(stateChanges.m_state, changesFromLastState));
            m_displayList.append(SetState::create(stateChanges.m_state, changesFromLastState));
            stateChanges.m_changeFlags = 0;
            currentState().lastDrawingState = stateChanges.m_state;
        }
        currentState().wasUsedForDrawing = true;
    }
}

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

void Recorder::clearShadow()
{
    appendItem(ClearShadow::create());
}

void Recorder::setLineCap(LineCap lineCap)
{
    appendItem(SetLineCap::create(lineCap));
}

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

void Recorder::setLineJoin(LineJoin lineJoin)
{
    appendItem(SetLineJoin::create(lineJoin));
}

void Recorder::setMiterLimit(float miterLimit)
{
    appendItem(SetMiterLimit::create(miterLimit));
}

void Recorder::drawGlyphs(const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawGlyphs::create(font, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs, FloatPoint(), toFloatSize(startPoint), smoothingMode)));
    updateItemExtent(newItem);
}

ImageDrawResult Recorder::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawImage::create(image, destination, source, imagePaintingOptions)));
    updateItemExtent(newItem);
    return ImageDrawResult::DidRecord;
}

ImageDrawResult Recorder::drawTiledImage(Image& image, const FloatRect& destination, const FloatPoint& source, const FloatSize& tileSize, const FloatSize& spacing, const ImagePaintingOptions& imagePaintingOptions)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawTiledImage::create(image, destination, source, tileSize, spacing, imagePaintingOptions)));
    updateItemExtent(newItem);
    return ImageDrawResult::DidRecord;
}

ImageDrawResult Recorder::drawTiledImage(Image& image, const FloatRect& destination, const FloatRect& source, const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRule, const ImagePaintingOptions& imagePaintingOptions)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawTiledScaledImage::create(image, destination, source, tileScaleFactor, hRule, vRule, imagePaintingOptions)));
    updateItemExtent(newItem);
    return ImageDrawResult::DidRecord;
}

#if USE(CG) || USE(CAIRO) || USE(DIRECT2D)
void Recorder::drawNativeImage(const NativeImagePtr& image, const FloatSize& imageSize, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawNativeImage::create(image, imageSize, destRect, srcRect, options)));
    updateItemExtent(newItem);
}
#endif

void Recorder::drawPattern(Image& image, const FloatRect& destRect, const FloatRect& tileRect, const AffineTransform& patternTransform, const FloatPoint& phase, const FloatSize& spacing, const ImagePaintingOptions& options)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawPattern::create(image, destRect, tileRect, patternTransform, phase, spacing, options)));
    updateItemExtent(newItem);
}

void Recorder::save()
{
    appendItem(Save::create());
    m_stateStack.append(m_stateStack.last().cloneForSave(m_displayList.itemCount() - 1));
}

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

    bool stateUsedForDrawing = currentState().wasUsedForDrawing;
    size_t saveIndex = currentState().saveItemIndex;

    m_stateStack.removeLast();
    // Have to avoid eliding nested Save/Restore when a descendant state contains drawing items.
    currentState().wasUsedForDrawing |= stateUsedForDrawing;

    if (!stateUsedForDrawing && saveIndex) {
        // This Save/Restore didn't contain any drawing items. Roll back to just before the last save.
        m_displayList.removeItemsFromIndex(saveIndex);
        return;
    }

    appendItem(Restore::create());

    if (saveIndex) {
        Save& saveItem = downcast<Save>(m_displayList.itemAt(saveIndex));
        saveItem.setRestoreIndex(m_displayList.itemCount() - 1);
    }
}

void Recorder::translate(float x, float y)
{
    currentState().translate(x, y);
    appendItem(Translate::create(x, y));
}

void Recorder::rotate(float angleInRadians)
{
    currentState().rotate(angleInRadians);
    appendItem(Rotate::create(angleInRadians));
}

void Recorder::scale(const FloatSize& size)
{
    currentState().scale(size);
    appendItem(Scale::create(size));
}

void Recorder::concatCTM(const AffineTransform& transform)
{
    currentState().concatCTM(transform);
    appendItem(ConcatenateCTM::create(transform));
}

void Recorder::setCTM(const AffineTransform&)
{
    WTFLogAlways("GraphicsContext::setCTM() is not compatible with DisplayList::Recorder.");
}

AffineTransform Recorder::getCTM(GraphicsContext::IncludeDeviceScale)
{
    WTFLogAlways("GraphicsContext::getCTM() is not yet compatible with DisplayList::Recorder.");
    return { };
}

void Recorder::beginTransparencyLayer(float opacity)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(BeginTransparencyLayer::create(opacity)));
    updateItemExtent(newItem);
}

void Recorder::endTransparencyLayer()
{
    appendItem(EndTransparencyLayer::create());
}

void Recorder::drawRect(const FloatRect& rect, float borderThickness)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawRect::create(rect, borderThickness)));
    updateItemExtent(newItem);
}

void Recorder::drawLine(const FloatPoint& point1, const FloatPoint& point2)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawLine::create(point1, point2)));
    updateItemExtent(newItem);
}

void Recorder::drawLinesForText(const FloatPoint& point, float thickness, const DashArray& widths, bool printing, bool doubleLines)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawLinesForText::create(FloatPoint(), toFloatSize(point), thickness, widths, printing, doubleLines)));
    updateItemExtent(newItem);
}

void Recorder::drawDotsForDocumentMarker(const FloatRect& rect, DocumentMarkerLineStyle style)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawDotsForDocumentMarker::create(rect, style)));
    updateItemExtent(newItem);
}

void Recorder::drawEllipse(const FloatRect& rect)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawEllipse::create(rect)));
    updateItemExtent(newItem);
}

void Recorder::drawPath(const Path& path)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawPath::create(path)));
    updateItemExtent(newItem);
}

void Recorder::drawFocusRing(const Path& path, float width, float offset, const Color& color)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawFocusRingPath::create(path, width, offset, color)));
    updateItemExtent(newItem);
}

void Recorder::drawFocusRing(const Vector<FloatRect>& rects, float width, float offset, const Color& color)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(DrawFocusRingRects::create(rects, width, offset, color)));
    updateItemExtent(newItem);
}

void Recorder::fillRect(const FloatRect& rect)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillRect::create(rect)));
    updateItemExtent(newItem);
}

void Recorder::fillRect(const FloatRect& rect, const Color& color)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillRectWithColor::create(rect, color)));
    updateItemExtent(newItem);
}

void Recorder::fillRect(const FloatRect& rect, Gradient& gradient)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillRectWithGradient::create(rect, gradient)));
    updateItemExtent(newItem);
}

void Recorder::fillRect(const FloatRect& rect, const Color& color, CompositeOperator op, BlendMode blendMode)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillCompositedRect::create(rect, color, op, blendMode)));
    updateItemExtent(newItem);
}

void Recorder::fillRoundedRect(const FloatRoundedRect& rect, const Color& color, BlendMode blendMode)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillRoundedRect::create(rect, color, blendMode)));
    updateItemExtent(newItem);
}

void Recorder::fillRectWithRoundedHole(const FloatRect& rect, const FloatRoundedRect& roundedHoleRect, const Color& color)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillRectWithRoundedHole::create(rect, roundedHoleRect, color)));
    updateItemExtent(newItem);
}

void Recorder::fillPath(const Path& path)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillPath::create(path)));
    updateItemExtent(newItem);
}

void Recorder::fillEllipse(const FloatRect& rect)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(FillEllipse::create(rect)));
    updateItemExtent(newItem);
}

void Recorder::strokeRect(const FloatRect& rect, float lineWidth)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(StrokeRect::create(rect, lineWidth)));
    updateItemExtent(newItem);
}

void Recorder::strokePath(const Path& path)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(StrokePath::create(path)));
    updateItemExtent(newItem);
}

void Recorder::strokeEllipse(const FloatRect& rect)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(StrokeEllipse::create(rect)));
    updateItemExtent(newItem);
}

void Recorder::clearRect(const FloatRect& rect)
{
    DrawingItem& newItem = downcast<DrawingItem>(appendItem(ClearRect::create(rect)));
    updateItemExtent(newItem);
}

#if USE(CG)
void Recorder::applyStrokePattern()
{
    appendItem(ApplyStrokePattern::create());
}

void Recorder::applyFillPattern()
{
    appendItem(ApplyFillPattern::create());
}
#endif

void Recorder::clip(const FloatRect& rect)
{
    currentState().clipBounds.intersect(rect);
    appendItem(Clip::create(rect));
}

void Recorder::clipOut(const FloatRect& rect)
{
    appendItem(ClipOut::create(rect));
}

void Recorder::clipOut(const Path& path)
{
    appendItem(ClipOutToPath::create(path));
}

void Recorder::clipPath(const Path& path, WindRule windRule)
{
    currentState().clipBounds.intersect(path.fastBoundingRect());
    appendItem(ClipPath::create(path, windRule));
}

IntRect Recorder::clipBounds()
{
    WTFLogAlways("Getting the clip bounds not yet supported with DisplayList::Recorder.");
    return IntRect(-2048, -2048, 4096, 4096);
}

void Recorder::clipToImageBuffer(ImageBuffer&, const FloatRect&)
{
    WTFLogAlways("GraphicsContext::clipToImageBuffer is not compatible with DisplayList::Recorder.");
}

void Recorder::applyDeviceScaleFactor(float deviceScaleFactor)
{
    // FIXME: this changes the baseCTM, which will invalidate all of our cached extents.
    // Assert that it's only called early on?
    appendItem(ApplyDeviceScaleFactor::create(deviceScaleFactor));
}

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

Item& Recorder::appendItem(Ref<Item>&& item)
{
    willAppendItem(item.get());
    return m_displayList.append(WTFMove(item));
}

void Recorder::updateItemExtent(DrawingItem& item) const
{
    if (Optional<FloatRect> rect = item.localBounds(graphicsContext()))
        item.setExtent(extentFromLocalBounds(rect.value()));
}

// FIXME: share with ShadowData
static inline float shadowPaintingExtent(float blurRadius)
{
    // Blurring uses a Gaussian function whose std. deviation is m_radius/2, and which in theory
    // extends to infinity. In 8-bit contexts, however, rounding causes the effect to become
    // undetectable at around 1.4x the radius.
    const float radiusExtentMultiplier = 1.4;
    return ceilf(blurRadius * radiusExtentMultiplier);
}

FloatRect Recorder::extentFromLocalBounds(const FloatRect& rect) const
{
    FloatRect bounds = rect;
    const ContextState& state = currentState();

    FloatSize shadowOffset;
    float shadowRadius;
    Color shadowColor;
    if (graphicsContext().getShadow(shadowOffset, shadowRadius, shadowColor)) {
        FloatRect shadowExtent= bounds;
        shadowExtent.move(shadowOffset);
        shadowExtent.inflate(shadowPaintingExtent(shadowRadius));
        bounds.unite(shadowExtent);
    }
    
    FloatRect clippedExtent = intersection(state.clipBounds, bounds);
    return state.ctm.mapRect(clippedExtent);
}

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;
}

const FloatRect& Recorder::clipBounds() const
{
    return currentState().clipBounds;
}

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

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

    if (Optional<AffineTransform> inverse = rotation.inverse())
        clipBounds = inverse.value().mapRect(clipBounds);
}

void Recorder::ContextState::scale(const FloatSize& size)
{
    ctm.scale(size);
    clipBounds.scale(1 / size.width(), 1 / size.height());
}

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

    if (Optional<AffineTransform> inverse = matrix.inverse())
        clipBounds = inverse.value().mapRect(clipBounds);
}

} // namespace DisplayList
} // namespace WebCore
