/*
 * Copyright (C) 2013 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. AND ITS CONTRIBUTORS ``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 ITS 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 "ImageQualityController.h"

#include "Frame.h"
#include "GraphicsContext.h"
#include "Page.h"
#include "RenderBoxModelObject.h"
#include "RenderView.h"

namespace WebCore {

static const double cInterpolationCutoff = 800. * 800.;
static const Seconds lowQualityTimeThreshold { 500_ms };

ImageQualityController::ImageQualityController(const RenderView& renderView)
    : m_renderView(renderView)
    , m_timer(*this, &ImageQualityController::highQualityRepaintTimerFired)
{
}

void ImageQualityController::removeLayer(RenderBoxModelObject* object, LayerSizeMap* innerMap, const void* layer)
{
    if (!innerMap)
        return;
    innerMap->remove(layer);
    if (innerMap->isEmpty())
        removeObject(object);
}

void ImageQualityController::set(RenderBoxModelObject* object, LayerSizeMap* innerMap, const void* layer, const LayoutSize& size)
{
    if (innerMap)
        innerMap->set(layer, size);
    else {
        LayerSizeMap newInnerMap;
        newInnerMap.set(layer, size);
        m_objectLayerSizeMap.set(object, newInnerMap);
    }
}

void ImageQualityController::removeObject(RenderBoxModelObject* object)
{
    m_objectLayerSizeMap.remove(object);
    if (m_objectLayerSizeMap.isEmpty()) {
        m_animatedResizeIsActive = false;
        m_timer.stop();
    }
}

void ImageQualityController::highQualityRepaintTimerFired()
{
    if (m_renderView.renderTreeBeingDestroyed())
        return;
    if (!m_animatedResizeIsActive && !m_liveResizeOptimizationIsActive)
        return;
    m_animatedResizeIsActive = false;

    // If the FrameView is in live resize, punt the timer and hold back for now.
    if (m_renderView.frameView().inLiveResize()) {
        restartTimer();
        return;
    }

    for (auto it = m_objectLayerSizeMap.begin(), end = m_objectLayerSizeMap.end(); it != end; ++it)
        it->key->repaint();

    m_liveResizeOptimizationIsActive = false;
}

void ImageQualityController::restartTimer()
{
    m_timer.startOneShot(lowQualityTimeThreshold);
}

std::optional<InterpolationQuality> ImageQualityController::interpolationQualityFromStyle(const RenderStyle& style)
{
    switch (style.imageRendering()) {
    case ImageRendering::OptimizeSpeed:
        return InterpolationQuality::Low;
    case ImageRendering::CrispEdges:
    case ImageRendering::Pixelated:
        return InterpolationQuality::DoNotInterpolate;
    case ImageRendering::OptimizeQuality:
        return InterpolationQuality::Default; // FIXME: CSS 3 Images says that optimizeQuality should behave like 'auto', but that prevents authors from overriding this low quality rendering behavior.
    case ImageRendering::Auto:
        break;
    }
    return std::nullopt;
}

InterpolationQuality ImageQualityController::chooseInterpolationQuality(GraphicsContext& context, RenderBoxModelObject* object, Image& image, const void* layer, const LayoutSize& size)
{
    // If the image is not a bitmap image, then none of this is relevant and we just paint at high quality.
    if (!(image.isBitmapImage() || image.isPDFDocumentImage()) || context.paintingDisabled())
        return InterpolationQuality::Default;

    if (std::optional<InterpolationQuality> styleInterpolation = interpolationQualityFromStyle(object->style()))
        return styleInterpolation.value();

    // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image
    // is actually being scaled.
    IntSize imageSize(image.width(), image.height());

    // Look ourselves up in the hashtables.
    auto i = m_objectLayerSizeMap.find(object);
    LayerSizeMap* innerMap = i != m_objectLayerSizeMap.end() ? &i->value : 0;
    LayoutSize oldSize;
    bool isFirstResize = true;
    if (innerMap) {
        LayerSizeMap::iterator j = innerMap->find(layer);
        if (j != innerMap->end()) {
            isFirstResize = false;
            oldSize = j->value;
        }
    }

    // If the containing FrameView is being resized, paint at low quality until resizing is finished.
    if (Frame* frame = object->document().frame()) {
        bool frameViewIsCurrentlyInLiveResize = frame->view() && frame->view()->inLiveResize();
        if (frameViewIsCurrentlyInLiveResize) {
            set(object, innerMap, layer, size);
            restartTimer();
            m_liveResizeOptimizationIsActive = true;
            return InterpolationQuality::Low;
        }
        if (m_liveResizeOptimizationIsActive)
            return InterpolationQuality::Default;
    }

    const AffineTransform& currentTransform = context.getCTM();
    bool contextIsScaled = !currentTransform.isIdentityOrTranslationOrFlipped();
    if (!contextIsScaled && size == imageSize) {
        // There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list.
        removeLayer(object, innerMap, layer);
        return InterpolationQuality::Default;
    }

    // There is no need to hash scaled images that always use low quality mode when the page demands it. This is the iChat case.
    if (m_renderView.page().inLowQualityImageInterpolationMode()) {
        double totalPixels = static_cast<double>(image.width()) * static_cast<double>(image.height());
        if (totalPixels > cInterpolationCutoff)
            return InterpolationQuality::Low;
    }

    // If an animated resize is active, paint in low quality and kick the timer ahead.
    if (m_animatedResizeIsActive) {
        set(object, innerMap, layer, size);
        restartTimer();
        return InterpolationQuality::Low;
    }
    // If this is the first time resizing this image, or its size is the
    // same as the last resize, draw at high res, but record the paint
    // size and set the timer.
    if (isFirstResize || oldSize == size) {
        restartTimer();
        set(object, innerMap, layer, size);
        return InterpolationQuality::Default;
    }
    // If the timer is no longer active, draw at high quality and don't
    // set the timer.
    if (!m_timer.isActive()) {
        removeLayer(object, innerMap, layer);
        return InterpolationQuality::Default;
    }
    // This object has been resized to two different sizes while the timer
    // is active, so draw at low quality, set the flag for animated resizes and
    // the object to the list for high quality redraw.
    set(object, innerMap, layer, size);
    m_animatedResizeIsActive = true;
    restartTimer();
    return InterpolationQuality::Low;
}

}
