/*
 * 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.
 */

#pragma once

#include "ScalableImageDecoder.h"
#include <stdint.h>

namespace WebCore {

// This class decodes a BMP image. It is used in the BMP and ICO decoders,
// which wrap it in the appropriate code to read file headers, etc.
class BMPImageReader {
    WTF_MAKE_FAST_ALLOCATED;
public:
    // Read a value from |data[offset]|, converting from little to native
    // endianness.
    static inline uint16_t readUint16(SharedBuffer* data, int offset)
    {
        uint16_t result;
        memcpy(&result, &data->data()[offset], 2);
#if CPU(BIG_ENDIAN)
        result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8);
#endif
        return result;
    }

    static inline uint32_t readUint32(SharedBuffer* data, int offset)
    {
        uint32_t result;
        memcpy(&result, &data->data()[offset], 4);
#if CPU(BIG_ENDIAN)
        result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24);
#endif
        return result;
    }

    // |parent| is the decoder that owns us.
    // |startOffset| points to the start of the BMP within the file.
    // |buffer| points at an empty ScalableImageDecoderFrame that we'll initialize and
    // fill with decoded data.
    BMPImageReader(ScalableImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask);

    void setBuffer(ScalableImageDecoderFrame* buffer) { m_buffer = buffer; }
    void setData(SharedBuffer* data) { m_data = data; }

    // Does the actual decoding. If |onlySize| is true, decoding only
    // progresses as far as necessary to get the image size. Returns
    // whether decoding succeeded.
    bool decodeBMP(bool onlySize);

private:
    // The various BMP compression types. We don't currently decode all
    // these.
    enum CompressionType {
        // Universal types
        RGB = 0,
        RLE8 = 1,
        RLE4 = 2,
        // Windows V3+ only
        BITFIELDS = 3,
        JPEG = 4,
        PNG = 5,
        // OS/2 2.x-only
        HUFFMAN1D, // Stored in file as 3
        RLE24, // Stored in file as 4
    };
    enum AndMaskState {
        None,
        NotYetDecoded,
        Decoding,
    };
    enum ProcessingResult {
        Success,
        Failure,
        InsufficientData,
    };

    // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
    // structs, but with unnecessary entries removed.
    struct BitmapInfoHeader {
        uint32_t biSize;
        int32_t biWidth;
        int32_t biHeight;
        uint16_t biBitCount;
        CompressionType biCompression;
        uint32_t biClrUsed;
    };
    struct RGBTriple {
        uint8_t rgbBlue;
        uint8_t rgbGreen;
        uint8_t rgbRed;
    };

    inline uint16_t readUint16(int offset) const
    {
        return readUint16(m_data.get(), m_decodedOffset + offset);
    }

    inline uint32_t readUint32(int offset) const
    {
        return readUint32(m_data.get(), m_decodedOffset + offset);
    }

    // Determines the size of the BMP info header. Returns true if the size
    // is valid.
    bool readInfoHeaderSize();

    // Processes the BMP info header. Returns true if the info header could
    // be decoded.
    bool processInfoHeader();

    // Helper function for processInfoHeader() which does the actual reading
    // of header values from the byte stream. Returns false on error.
    bool readInfoHeader();

    // Returns true if this is a Windows V4+ BMP.
    inline bool isWindowsV4Plus() const
    {
        // Windows V4 info header is 108 bytes. V5 is 124 bytes.
        return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124);
    }

    // Returns false if consistency errors are found in the info header.
    bool isInfoHeaderValid() const;

    // For BI_BITFIELDS images, initializes the m_bitMasks[] and
    // m_bitOffsets[] arrays. processInfoHeader() will initialize these for
    // other compression types where needed.
    bool processBitmasks();

    // For paletted images, allocates and initializes the m_colorTable[]
    // array.
    bool processColorTable();

    // Processes an RLE-encoded image. Returns true if the entire image was
    // decoded.
    bool processRLEData();

    // Processes a set of non-RLE-compressed pixels. Two cases:
    //   * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to
    //     process |numPixels| pixels on the current row.
    //   * inRLE = false: the data is inside a non-RLE-encoded bitmap.
    //     |numPixels| is ignored. Expects |m_coord| to point at the
    //     beginning of the next row to be decoded. Tries to process as
    //     many complete rows as possible. Returns InsufficientData if
    //     there wasn't enough data to decode the whole image.
    //
    // This function returns a ProcessingResult instead of a bool so that it
    // can avoid calling m_parent->setFailed(), which could lead to memory
    // corruption since that will delete |this| but some callers still want
    // to access member variables after this returns.
    ProcessingResult processNonRLEData(bool inRLE, int numPixels);

    // Returns true if the current y-coordinate plus |numRows| would be past
    // the end of the image. Here "plus" means "toward the end of the
    // image", so downwards for m_isTopDown images and upwards otherwise.
    inline bool pastEndOfImage(int numRows)
    {
        return m_isTopDown ? ((m_coord.y() + numRows) >= m_parent->size().height()) : ((m_coord.y() - numRows) < 0);
    }

    // Returns the pixel data for the current X coordinate in a uint32_t.
    // Assumes m_decodedOffset has been set to the beginning of the current
    // row.
    // NOTE: Only as many bytes of the return value as are needed to hold
    // the pixel data will actually be set.
    inline uint32_t readCurrentPixel(int bytesPerPixel) const
    {
        const int offset = m_coord.x() * bytesPerPixel;
        switch (bytesPerPixel) {
        case 2:
            return readUint16(offset);

        case 3: {
            // It doesn't matter that we never set the most significant byte
            // of the return value here in little-endian mode, the caller
            // won't read it.
            uint32_t pixel;
            memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3);
#if CPU(BIG_ENDIAN)
            pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24);
#endif
            return pixel;
        }

        case 4:
            return readUint32(offset);

        default:
            ASSERT_NOT_REACHED();
            return 0;
        }
    }

    // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A)
    // in the given pixel data.
    inline unsigned getComponent(uint32_t pixel, int component) const
    {
        return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component]) << m_bitShiftsLeft[component];
    }

    inline unsigned getAlpha(uint32_t pixel) const
    {
        // For images without alpha, return alpha of 0xff.
        return m_bitMasks[3] ? getComponent(pixel, 3) : 0xff;
    }

    // Sets the current pixel to the color given by |colorIndex|. This also
    // increments the relevant local variables to move the current pixel
    // right by one.
    inline void setI(size_t colorIndex)
    {
        setPixel(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff);
    }

    // Like setI(), but with the individual component values specified.
    inline void setPixel(unsigned red, unsigned green, unsigned blue, unsigned alpha)
    {
        m_buffer->backingStore()->setPixel(m_coord.x(), m_coord.y(), red, green, blue, alpha);
        m_coord.move(1, 0);
    }

    // Fills pixels from the current X-coordinate up to, but not including,
    // |endCoord| with the color given by the individual components. This
    // also increments the relevant local variables to move the current
    // pixel right to |endCoord|.
    inline void fillRGBA(int endCoord, unsigned red, unsigned green, unsigned blue, unsigned alpha)
    {
        if (endCoord <= m_coord.x())
            return;
        m_buffer->backingStore()->fillRect(IntRect(m_coord.x(), m_coord.y(), endCoord - m_coord.x(), 1), red, green, blue, alpha);
        m_coord.setX(endCoord);
    }

    // Resets the relevant local variables to start drawing at the left edge
    // of the "next" row, where "next" is above or below the current row
    // depending on the value of |m_isTopDown|.
    void moveBufferToNextRow();

    // The decoder that owns us.
    ScalableImageDecoder* m_parent;

    // The destination for the pixel data.
    ScalableImageDecoderFrame* m_buffer;

    // The file to decode.
    RefPtr<SharedBuffer> m_data;

    // An index into |m_data| representing how much we've already decoded.
    size_t m_decodedOffset;

    // The file offset at which the BMP info header starts.
    size_t m_headerOffset;

    // The file offset at which the actual image bits start. When decoding
    // ICO files, this is set to 0, since it's not stored anywhere in a
    // header; the reader functions expect the image data to start
    // immediately after the header and (if necessary) color table.
    size_t m_imgDataOffset;

    // The BMP info header.
    BitmapInfoHeader m_infoHeader;

    // True if this is an OS/2 1.x (aka Windows 2.x) BMP. The struct
    // layouts for this type of BMP are slightly different from the later,
    // more common formats.
    bool m_isOS21x;

    // True if this is an OS/2 2.x BMP. The meanings of compression types 3
    // and 4 for this type of BMP differ from Windows V3+ BMPs.
    //
    // This will be falsely negative in some cases, but only ones where the
    // way we misinterpret the data is irrelevant.
    bool m_isOS22x;

    // True if the BMP is not vertically flipped, that is, the first line of
    // raster data in the file is the top line of the image.
    bool m_isTopDown;

    // These flags get set to false as we finish each processing stage.
    bool m_needToProcessBitmasks;
    bool m_needToProcessColorTable;

    // Masks/offsets for the color values for non-palette formats. These
    // are bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B,
    // A.
    //
    // The right/left shift values are meant to be applied after the masks.
    // We need to right shift to compensate for the bitfields' offsets into
    // the 32 bits of pixel data, and left shift to scale the color values
    // up for fields with less than 8 bits of precision. Sadly, we can't
    // just combine these into one shift value because the net shift amount
    // could go either direction. (If only "<< -x" were equivalent to
    // ">> x"...)
    uint32_t m_bitMasks[4];
    int m_bitShiftsRight[4];
    int m_bitShiftsLeft[4];

    // The color palette, for paletted formats.
    size_t m_tableSizeInBytes;
    Vector<RGBTriple> m_colorTable;

    // The coordinate to which we've decoded the image.
    IntPoint m_coord;

    // Variables that track whether we've seen pixels with alpha values != 0
    // and == 0, respectively. See comments in processNonRLEData() on how
    // these are used.
    bool m_seenNonZeroAlphaPixel;
    bool m_seenZeroAlphaPixel;

    // ICOs store a 1bpp "mask" immediately after the main bitmap image data
    // (and, confusingly, add its height to the biHeight value in the info
    // header, thus doubling it). This variable tracks whether we have such
    // a mask and if we've started decoding it yet.
    AndMaskState m_andMaskState;
};

} // namespace WebCore
