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

#include "Image.h"
#include "ImageData.h"

namespace WebCore {

ImageBufferBackend::ImageBufferBackend(const FloatSize& logicalSize, const IntSize& backendSize, float resolutionScale, ColorSpace colorSpace)
    : m_logicalSize(logicalSize)
    , m_backendSize(backendSize)
    , m_resolutionScale(resolutionScale)
    , m_colorSpace(colorSpace)
{
}

IntSize ImageBufferBackend::calculateBackendSize(const FloatSize& size, float resolutionScale)
{
    FloatSize scaledSize = { ceilf(resolutionScale * size.width()), ceilf(resolutionScale * size.height()) };
    if (scaledSize.isEmpty() || !scaledSize.isExpressibleAsIntSize())
        return { };

    IntSize backendSize = IntSize(scaledSize);

    Checked<unsigned, RecordOverflow> bytesPerRow = 4 * Checked<unsigned, RecordOverflow>(backendSize.width());
    if (bytesPerRow.hasOverflowed())
        return { };

    Checked<size_t, RecordOverflow> numBytes = Checked<unsigned, RecordOverflow>(backendSize.height()) * bytesPerRow;
    if (numBytes.hasOverflowed())
        return { };

    return backendSize;
}

NativeImagePtr ImageBufferBackend::sinkIntoNativeImage()
{
    return copyNativeImage(DontCopyBackingStore);
}

RefPtr<Image> ImageBufferBackend::sinkIntoImage(PreserveResolution preserveResolution)
{
    return copyImage(DontCopyBackingStore, preserveResolution);
}

void ImageBufferBackend::drawConsuming(GraphicsContext& destContext, const FloatRect& destRect, const FloatRect& srcRect, const ImagePaintingOptions& options)
{
    draw(destContext, destRect, srcRect, options);
}

void ImageBufferBackend::convertToLuminanceMask()
{
    auto imageData = getImageData(AlphaPremultiplication::Unpremultiplied, logicalRect());
    if (!imageData)
        return;

    auto* srcPixelArray = imageData->data();
    unsigned pixelArrayLength = srcPixelArray->length();
    for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
        uint8_t a = srcPixelArray->item(pixelOffset + 3);
        if (!a)
            continue;
        uint8_t r = srcPixelArray->item(pixelOffset);
        uint8_t g = srcPixelArray->item(pixelOffset + 1);
        uint8_t b = srcPixelArray->item(pixelOffset + 2);

        double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
        srcPixelArray->set(pixelOffset + 3, luma);
    }

    putImageData(AlphaPremultiplication::Unpremultiplied, *imageData, logicalRect(), IntPoint::zero());
}

Vector<uint8_t> ImageBufferBackend::toBGRAData(void* data) const
{
    Vector<uint8_t> result(4 * m_logicalSize.area().unsafeGet());
    size_t destBytesPerRow = m_logicalSize.width() * 4;
    size_t srcBytesPerRow = bytesPerRow();

    uint8_t* srcRows = reinterpret_cast<uint8_t*>(data);

    copyImagePixels(
        AlphaPremultiplication::Premultiplied, backendColorFormat(), srcBytesPerRow, srcRows,
        AlphaPremultiplication::Unpremultiplied, ColorFormat::BGRA, destBytesPerRow, result.data(), m_logicalSize);

    return result;
}

static inline void copyPremultipliedToPremultiplied(ColorFormat srcColorFormat, const uint8_t* srcPixel, ColorFormat destColorFormat, uint8_t* destPixel)
{
    uint8_t alpha = srcPixel[3];
    if (!alpha) {
        reinterpret_cast<uint32_t*>(destPixel)[0] = 0;
        return;
    }

    if (srcColorFormat == destColorFormat) {
        reinterpret_cast<uint32_t*>(destPixel)[0] = reinterpret_cast<const uint32_t*>(srcPixel)[0];
        return;
    }

    // Swap pixel channels BGRA <-> RGBA.
    destPixel[0] = srcPixel[2];
    destPixel[1] = srcPixel[1];
    destPixel[2] = srcPixel[0];
    destPixel[3] = srcPixel[3];
}

static inline void copyPremultipliedToUnpremultiplied(ColorFormat srcColorFormat, const uint8_t* srcPixel, ColorFormat destColorFormat, uint8_t* destPixel)
{
    uint8_t alpha = srcPixel[3];
    if (!alpha || alpha == 255) {
        copyPremultipliedToPremultiplied(srcColorFormat, srcPixel, destColorFormat, destPixel);
        return;
    }

    if (srcColorFormat == destColorFormat) {
        destPixel[0] = (srcPixel[0] * 255) / alpha;
        destPixel[1] = (srcPixel[1] * 255) / alpha;
        destPixel[2] = (srcPixel[2] * 255) / alpha;
        destPixel[3] = alpha;
        return;
    }

    // Swap pixel channels BGRA <-> RGBA.
    destPixel[0] = (srcPixel[2] * 255) / alpha;
    destPixel[1] = (srcPixel[1] * 255) / alpha;
    destPixel[2] = (srcPixel[0] * 255) / alpha;
    destPixel[3] = alpha;
}

static inline void copyUnpremultipliedToPremultiplied(ColorFormat srcColorFormat, const uint8_t* srcPixel, ColorFormat destColorFormat, uint8_t* destPixel)
{
    uint8_t alpha = srcPixel[3];
    if (!alpha || alpha == 255) {
        copyPremultipliedToPremultiplied(srcColorFormat, srcPixel, destColorFormat, destPixel);
        return;
    }

    if (srcColorFormat == destColorFormat) {
        destPixel[0] = (srcPixel[0] * alpha + 254) / 255;
        destPixel[1] = (srcPixel[1] * alpha + 254) / 255;
        destPixel[2] = (srcPixel[2] * alpha + 254) / 255;
        destPixel[3] = alpha;
        return;
    }

    // Swap pixel channels BGRA <-> RGBA.
    destPixel[0] = (srcPixel[2] * alpha + 254) / 255;
    destPixel[1] = (srcPixel[1] * alpha + 254) / 255;
    destPixel[2] = (srcPixel[0] * alpha + 254) / 255;
    destPixel[3] = alpha;
}

template<void (*copyFunctor)(ColorFormat, const uint8_t*, ColorFormat, uint8_t*)>
static inline void copyImagePixelsUnaccelerated(
    ColorFormat srcColorFormat, unsigned srcBytesPerRow, uint8_t* srcRows,
    ColorFormat destColorFormat, unsigned destBytesPerRow, uint8_t* destRows, const IntSize& size)
{
    size_t bytesPerRow = size.width() * 4;
    for (int y = 0; y < size.height(); ++y) {
        for (size_t x = 0; x < bytesPerRow; x += 4)
            copyFunctor(srcColorFormat, &srcRows[x], destColorFormat, &destRows[x]);
        srcRows += srcBytesPerRow;
        destRows += destBytesPerRow;
    }
}

void ImageBufferBackend::copyImagePixels(
    AlphaPremultiplication srcAlphaFormat, ColorFormat srcColorFormat, unsigned srcBytesPerRow, uint8_t* srcRows,
    AlphaPremultiplication destAlphaFormat, ColorFormat destColorFormat, unsigned destBytesPerRow, uint8_t* destRows, const IntSize& size) const
{
    if (srcAlphaFormat == destAlphaFormat) {
        ASSERT(srcAlphaFormat == AlphaPremultiplication::Premultiplied && destAlphaFormat == AlphaPremultiplication::Premultiplied);
        copyImagePixelsUnaccelerated<copyPremultipliedToPremultiplied>(srcColorFormat, srcBytesPerRow, srcRows, destColorFormat, destBytesPerRow, destRows, size);
        return;
    }

    if (destAlphaFormat == AlphaPremultiplication::Unpremultiplied) {
        copyImagePixelsUnaccelerated<copyPremultipliedToUnpremultiplied>(srcColorFormat, srcBytesPerRow, srcRows, destColorFormat, destBytesPerRow, destRows, size);
        return;
    }

    copyImagePixelsUnaccelerated<copyUnpremultipliedToPremultiplied>(srcColorFormat, srcBytesPerRow, srcRows, destColorFormat, destBytesPerRow, destRows, size);
}

RefPtr<ImageData> ImageBufferBackend::getImageData(AlphaPremultiplication outputFormat, const IntRect& srcRect, void* data) const
{
    IntRect srcRectScaled = toBackendCoordinates(srcRect);

    auto imageData = ImageData::create(srcRectScaled.size());
    if (!imageData || !imageData->data())
        return nullptr;

    IntRect srcRectClipped =  intersection(backendRect(), srcRectScaled);
    IntRect destRect = { IntPoint::zero(), srcRectClipped.size() };

    if (srcRectScaled.x() < 0)
        destRect.setX(-srcRectScaled.x());

    if (srcRectScaled.y() < 0)
        destRect.setY(-srcRectScaled.y());

    if (destRect.size() != srcRectScaled.size())
        imageData->data()->zeroFill();

    unsigned destBytesPerRow = 4 * srcRectScaled.width();
    uint8_t* destRows = imageData->data()->data() + destRect.y() * destBytesPerRow + destRect.x() * 4;

    unsigned srcBytesPerRow = bytesPerRow();
    uint8_t* srcRows = reinterpret_cast<uint8_t*>(data) + srcRectClipped.y() * srcBytesPerRow + srcRectClipped.x() * 4;

    copyImagePixels(
        AlphaPremultiplication::Premultiplied, backendColorFormat(), srcBytesPerRow, srcRows,
        outputFormat, ColorFormat::RGBA, destBytesPerRow, destRows, destRect.size());

    return imageData;
}

void ImageBufferBackend::putImageData(AlphaPremultiplication inputFormat, const ImageData& imageData, const IntRect& srcRect, const IntPoint& destPoint, void* data)
{
    IntRect srcRectScaled = toBackendCoordinates(srcRect);
    IntPoint destPointScaled = toBackendCoordinates(destPoint);

    IntRect srcRectClipped = intersection({ IntPoint::zero(), imageData.size() }, srcRectScaled);
    IntRect destRect = srcRectClipped;
    destRect.moveBy(destPointScaled);

    if (srcRectScaled.x() < 0)
        destRect.setX(destRect.x() - srcRectScaled.x());

    if (srcRectScaled.y() < 0)
        destRect.setY(destRect.y() - srcRectScaled.y());

    destRect.intersect(backendRect());
    srcRectClipped.setSize(destRect.size());

    unsigned destBytesPerRow = bytesPerRow();
    uint8_t* destRows = reinterpret_cast<uint8_t*>(data) + destRect.y() * destBytesPerRow + destRect.x() * 4;

    unsigned srcBytesPerRow = 4 * imageData.size().width();
    uint8_t* srcRows = imageData.data()->data() + srcRectClipped.y() * srcBytesPerRow + srcRectClipped.x() * 4;

    copyImagePixels(
        inputFormat, ColorFormat::RGBA, srcBytesPerRow, srcRows,
        AlphaPremultiplication::Premultiplied, backendColorFormat(), destBytesPerRow, destRows, destRect.size());
}

} // namespace WebCore
