/*
 * Copyright (c) 2008, 2009, Google 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:
 * 
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER 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 "ICOImageDecoder.h"

#include <algorithm>

#include "BMPImageReader.h"
#include "PNGImageDecoder.h"

namespace WebCore {

// Number of bits in .ICO/.CUR used to store the directory and its entries,
// respectively (doesn't match sizeof values for member structs since we omit
// some fields).
static const size_t sizeOfDirectory = 6;
static const size_t sizeOfDirEntry = 16;

ICOImageDecoder::ICOImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
    : ScalableImageDecoder(alphaOption, gammaAndColorProfileOption)
    , m_decodedOffset(0)
{
}

ICOImageDecoder::~ICOImageDecoder() = default;

void ICOImageDecoder::setData(SharedBuffer& data, bool allDataReceived)
{
    if (failed())
        return;

    ScalableImageDecoder::setData(data, allDataReceived);

    for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end(); ++i) {
        if (*i)
            (*i)->setData(*m_data);
    }
    for (size_t i = 0; i < m_pngDecoders.size(); ++i)
        setDataForPNGDecoderAtIndex(i);
}

IntSize ICOImageDecoder::size() const
{
    return m_frameSize.isEmpty() ? ScalableImageDecoder::size() : m_frameSize;
}

IntSize ICOImageDecoder::frameSizeAtIndex(size_t index, SubsamplingLevel) const
{
    return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size();
}

bool ICOImageDecoder::setSize(const IntSize& size)
{
    // The size calculated inside the BMPImageReader had better match the one in
    // the icon directory.
    return m_frameSize.isEmpty() ? ScalableImageDecoder::setSize(size) : ((size == m_frameSize) || setFailed());
}

size_t ICOImageDecoder::frameCount() const
{
    const_cast<ICOImageDecoder*>(this)->decode(0, true, isAllDataReceived());
    return m_frameBufferCache.size();
}

ScalableImageDecoderFrame* ICOImageDecoder::frameBufferAtIndex(size_t index)
{
    // Ensure |index| is valid.
    if (index >= frameCount())
        return 0;

    auto* buffer = &m_frameBufferCache[index];
    if (!buffer->isComplete())
        decode(index, false, isAllDataReceived());
    return buffer;
}

bool ICOImageDecoder::setFailed()
{
    m_bmpReaders.clear();
    m_pngDecoders.clear();
    return ScalableImageDecoder::setFailed();
}

Optional<IntPoint> ICOImageDecoder::hotSpot() const
{
    // When unspecified, the default frame is always frame 0. This is consistent with
    // BitmapImage where currentFrame() starts at 0 and only increases when animation is
    // requested.
    return hotSpotAtIndex(0);
}

Optional<IntPoint> ICOImageDecoder::hotSpotAtIndex(size_t index) const
{
    if (index >= m_dirEntries.size() || m_fileType != CURSOR)
        return WTF::nullopt;

    return m_dirEntries[index].m_hotSpot;
}


// static
bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b)
{
    // Larger icons are better.  After that, higher bit-depth icons are better.
    const int aEntryArea = a.m_size.width() * a.m_size.height();
    const int bEntryArea = b.m_size.width() * b.m_size.height();
    return (aEntryArea == bEntryArea) ? (a.m_bitCount > b.m_bitCount) : (aEntryArea > bEntryArea);
}

void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index)
{
    if (!m_pngDecoders[index])
        return;

    const IconDirectoryEntry& dirEntry = m_dirEntries[index];
    // Copy out PNG data to a separate vector and send to the PNG decoder.
    // FIXME: Save this copy by making the PNG decoder able to take an
    // optional offset.
    auto pngData = SharedBuffer::create(&m_data->data()[dirEntry.m_imageOffset], m_data->size() - dirEntry.m_imageOffset);
    m_pngDecoders[index]->setData(pngData.get(), isAllDataReceived());
}

void ICOImageDecoder::decode(size_t index, bool onlySize, bool allDataReceived)
{
    if (failed())
        return;

    // If we couldn't decode the image but we've received all the data, decoding
    // has failed.
    if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && allDataReceived)
        setFailed();
    // If we're done decoding this frame, we don't need the BMPImageReader or
    // PNGImageDecoder anymore.  (If we failed, these have already been
    // cleared.)
    else if ((m_frameBufferCache.size() > index) && m_frameBufferCache[index].isComplete()) {
        m_bmpReaders[index] = nullptr;
        m_pngDecoders[index] = nullptr;
    }
    
    if (m_frameBufferCache.isEmpty())
        m_frameBufferCache.grow(m_dirEntries.size());
    // CAUTION: We must not resize m_frameBufferCache again after this, as
    // decodeAtIndex() may give a BMPImageReader a pointer to one of the
    // entries.
}

bool ICOImageDecoder::decodeDirectory()
{
    // Read and process directory.
    if ((m_decodedOffset < sizeOfDirectory) && !processDirectory())
        return false;

    // Read and process directory entries.
    return (m_decodedOffset >= (sizeOfDirectory + (m_dirEntries.size() * sizeOfDirEntry))) || processDirectoryEntries();
}

bool ICOImageDecoder::decodeAtIndex(size_t index)
{
    ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size());
    const IconDirectoryEntry& dirEntry = m_dirEntries[index];
    const ImageType imageType = imageTypeAtIndex(index);
    if (imageType == Unknown)
        return false; // Not enough data to determine image type yet.

    if (imageType == BMP) {
        if (!m_bmpReaders[index]) {
            // We need to have already sized m_frameBufferCache before this, and
            // we must not resize it again later (see caution in frameCount()).
            ASSERT(m_frameBufferCache.size() == m_dirEntries.size());
            m_bmpReaders[index] = makeUnique<BMPImageReader>(this, dirEntry.m_imageOffset, 0, true);
            m_bmpReaders[index]->setData(*m_data);
            m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]);
        }
        m_frameSize = dirEntry.m_size;
        bool result = m_bmpReaders[index]->decodeBMP(false);
        m_frameSize = IntSize();
        return result;
    }

    if (!m_pngDecoders[index]) {
        m_pngDecoders[index] = PNGImageDecoder::create(m_premultiplyAlpha ? AlphaOption::Premultiplied : AlphaOption::NotPremultiplied, m_ignoreGammaAndColorProfile ? GammaAndColorProfileOption::Ignored : GammaAndColorProfileOption::Applied);
        setDataForPNGDecoderAtIndex(index);
    }
    // Fail if the size the PNGImageDecoder calculated does not match the size
    // in the directory.
    if (m_pngDecoders[index]->encodedDataStatus() >= EncodedDataStatus::SizeAvailable && (m_pngDecoders[index]->size() != dirEntry.m_size))
        return setFailed();
    m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0);
    return !m_pngDecoders[index]->failed() || setFailed();
}

bool ICOImageDecoder::processDirectory()
{
    // Read directory.
    ASSERT(!m_decodedOffset);
    if (m_data->size() < sizeOfDirectory)
        return false;
    const uint16_t fileType = readUint16(2);
    const uint16_t idCount = readUint16(4);
    m_decodedOffset = sizeOfDirectory;

    // See if this is an icon filetype we understand, and make sure we have at
    // least one entry in the directory.
    if (((fileType != ICON) && (fileType != CURSOR)) || (!idCount))
        return setFailed();

    m_fileType = static_cast<FileType>(fileType);

    // Enlarge member vectors to hold all the entries.
    m_dirEntries.resize(idCount);
    m_bmpReaders.resize(idCount);
    m_pngDecoders.resize(idCount);
    return true;
}

bool ICOImageDecoder::processDirectoryEntries()
{
    // Read directory entries.
    ASSERT(m_decodedOffset == sizeOfDirectory);
    if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < (m_dirEntries.size() * sizeOfDirEntry)))
        return false;
    for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i)
        *i = readDirectoryEntry();  // Updates m_decodedOffset.

    // Make sure the specified image offsets are past the end of the directory
    // entries.
    for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) {
        if (i->m_imageOffset < m_decodedOffset)
            return setFailed();
    }

    // Arrange frames in decreasing quality order.
    std::sort(m_dirEntries.begin(), m_dirEntries.end(), compareEntries);

    // The image size is the size of the largest entry.
    const IconDirectoryEntry& dirEntry = m_dirEntries.first();
    // Technically, this next call shouldn't be able to fail, since the width
    // and height here are each <= 256, and |m_frameSize| is empty.
    return setSize(dirEntry.m_size);
}

ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry()
{
    // Read icon data.
    // The casts to uint8_t in the next few lines are because that's the on-disk
    // type of the width and height values.  Storing them in ints (instead of
    // matching uint8_ts) is so we can record dimensions of size 256 (which is
    // what a zero byte really means).
    int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]);
    if (!width)
        width = 256;
    int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]);
    if (!height)
        height = 256;
    IconDirectoryEntry entry;
    entry.m_size = IntSize(width, height);
    if (m_fileType == CURSOR) {
        entry.m_bitCount = 0;
        entry.m_hotSpot = IntPoint(readUint16(4), readUint16(6));
    } else {
        entry.m_bitCount = readUint16(6);
        entry.m_hotSpot = IntPoint();
    }
    entry.m_imageOffset = readUint32(12);

    // Some icons don't have a bit depth, only a color count.  Convert the
    // color count to the minimum necessary bit depth.  It doesn't matter if
    // this isn't quite what the bitmap info header says later, as we only use
    // this value to determine which icon entry is best.
    if (!entry.m_bitCount) {
        int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2]);
        if (!colorCount)
            colorCount = 256;  // Vague in the spec, needed by real-world icons.
        for (--colorCount; colorCount; colorCount >>= 1)
            ++entry.m_bitCount;
    }

    m_decodedOffset += sizeOfDirEntry;
    return entry;
}

ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index)
{
    // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic
    // number.
    ASSERT_WITH_SECURITY_IMPLICATION(index < m_dirEntries.size());
    const uint32_t imageOffset = m_dirEntries[index].m_imageOffset;
    if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4))
        return Unknown;
    return strncmp(&m_data->data()[imageOffset], "\x89PNG", 4) ? BMP : PNG;
}

}
