1635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project/*
2635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
3635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
4635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Redistribution and use in source and binary forms, with or without
5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * modification, are permitted provided that the following conditions are
6635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * met:
7635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
8635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions of source code must retain the above copyright
9635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * notice, this list of conditions and the following disclaimer.
10635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Redistributions in binary form must reproduce the above
11635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * copyright notice, this list of conditions and the following disclaimer
12635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * in the documentation and/or other materials provided with the
13635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * distribution.
14635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *     * Neither the name of Google Inc. nor the names of its
15635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * contributors may be used to endorse or promote products derived from
16635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * this software without specific prior written permission.
17635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project *
18635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project */
30635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
31635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#ifndef BMPImageReader_h
32635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#define BMPImageReader_h
33635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
34635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <stdint.h>
35635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "ImageDecoder.h"
36635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
37635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectnamespace WebCore {
38635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // This class decodes a BMP image.  It is used in the BMP and ICO decoders,
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // which wrap it in the appropriate code to read file headers, etc.
410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    class BMPImageReader {
42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    public:
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Read a value from |data[offset]|, converting from little to native
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // endianness.
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        static inline uint16_t readUint16(SharedBuffer* data, int offset)
46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
47635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint16_t result;
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            memcpy(&result, &data->data()[offset], 2);
49d0825bca7fe65beaee391d30da42e937db621564Steve Block        #if CPU(BIG_ENDIAN)
50635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8);
51635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        #endif
52635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return result;
53635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
54635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        static inline uint32_t readUint32(SharedBuffer* data, int offset)
56635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
57635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint32_t result;
580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            memcpy(&result, &data->data()[offset], 4);
59d0825bca7fe65beaee391d30da42e937db621564Steve Block        #if CPU(BIG_ENDIAN)
60692e5dbf12901edacf14812a6fae25462920af42Steve Block            result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24);
61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        #endif
62635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return result;
63635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
64635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // |parent| is the decoder that owns us.
660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // |startOffset| points to the start of the BMP within the file.
6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // |buffer| points at an empty ImageFrame that we'll initialize and
680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // fill with decoded data.
69692e5dbf12901edacf14812a6fae25462920af42Steve Block        BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask);
70635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        void setBuffer(ImageFrame* buffer) { m_buffer = buffer; }
720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        void setData(SharedBuffer* data) { m_data = data; }
73635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Does the actual decoding.  If |onlySize| is true, decoding only
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // progresses as far as necessary to get the image size.  Returns
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // whether decoding succeeded.
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool decodeBMP(bool onlySize);
78635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
79635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    private:
800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The various BMP compression types.  We don't currently decode all
810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // these.
82635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        enum CompressionType {
83635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Universal types
84635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RGB = 0,
85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RLE8 = 1,
86635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RLE4 = 2,
87635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Windows V3+ only
88635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            BITFIELDS = 3,
89635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            JPEG = 4,
90635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            PNG = 5,
91635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // OS/2 2.x-only
92635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            HUFFMAN1D,  // Stored in file as 3
93635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            RLE24,      // Stored in file as 4
94635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        };
950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        enum AndMaskState {
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            None,
970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            NotYetDecoded,
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            Decoding,
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        };
10006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        enum ProcessingResult {
10106ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            Success,
10206ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            Failure,
10306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen            InsufficientData,
10406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        };
105635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // structs, but with unnecessary entries removed.
108635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        struct BitmapInfoHeader {
109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint32_t biSize;
110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            int32_t biWidth;
111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            int32_t biHeight;
112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint16_t biBitCount;
113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            CompressionType biCompression;
114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint32_t biClrUsed;
115635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        };
116635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        struct RGBTriple {
117635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint8_t rgbBlue;
118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint8_t rgbGreen;
119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            uint8_t rgbRed;
120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        };
121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        inline uint16_t readUint16(int offset) const
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        {
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return readUint16(m_data.get(), m_decodedOffset + offset);
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
126635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        inline uint32_t readUint32(int offset) const
1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        {
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return readUint32(m_data.get(), m_decodedOffset + offset);
1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Determines the size of the BMP info header.  Returns true if the size
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // is valid.
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool readInfoHeaderSize();
135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Processes the BMP info header.  Returns true if the info header could
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // be decoded.
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool processInfoHeader();
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Helper function for processInfoHeader() which does the actual reading
1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // of header values from the byte stream.  Returns false on error.
1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool readInfoHeader();
143635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
144635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Returns true if this is a Windows V4+ BMP.
145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inline bool isWindowsV4Plus() const
146635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
147635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Windows V4 info header is 108 bytes.  V5 is 124 bytes.
148635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124);
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
150635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
151635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Returns false if consistency errors are found in the info header.
152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool isInfoHeaderValid() const;
153635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // For BI_BITFIELDS images, initializes the m_bitMasks[] and
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // m_bitOffsets[] arrays.  processInfoHeader() will initialize these for
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // other compression types where needed.
1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool processBitmasks();
158635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // For paletted images, allocates and initializes the m_colorTable[]
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // array.
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool processColorTable();
162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
163635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Processes an RLE-encoded image.  Returns true if the entire image was
164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // decoded.
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        bool processRLEData();
166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
167635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Processes a set of non-RLE-compressed pixels.  Two cases:
168635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //   * inRLE = true: the data is inside an RLE-encoded bitmap.  Tries to
16906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        //     process |numPixels| pixels on the current row.
170635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //   * inRLE = false: the data is inside a non-RLE-encoded bitmap.
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        //     |numPixels| is ignored.  Expects |m_coord| to point at the
1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        //     beginning of the next row to be decoded.  Tries to process as
17306ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        //     many complete rows as possible.  Returns InsufficientData if
17406ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        //     there wasn't enough data to decode the whole image.
17506ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        //
17606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // This function returns a ProcessingResult instead of a bool so that it
17706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // can avoid calling m_parent->setFailed(), which could lead to memory
17806ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // corruption since that will delete |this| but some callers still want
17906ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        // to access member variables after this returns.
18006ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen        ProcessingResult processNonRLEData(bool inRLE, int numPixels);
181635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
182635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Returns true if the current y-coordinate plus |numRows| would be past
1830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // the end of the image.  Here "plus" means "toward the end of the
1840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // image", so downwards for m_isTopDown images and upwards otherwise.
185635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inline bool pastEndOfImage(int numRows)
186635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
187692e5dbf12901edacf14812a6fae25462920af42Steve Block            return m_isTopDown ? ((m_coord.y() + numRows) >= m_parent->size().height()) : ((m_coord.y() - numRows) < 0);
188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
189635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
190635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Returns the pixel data for the current X coordinate in a uint32_t.
191635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Assumes m_decodedOffset has been set to the beginning of the current
192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // row.
1930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // NOTE: Only as many bytes of the return value as are needed to hold
1940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // the pixel data will actually be set.
1950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        inline uint32_t readCurrentPixel(int bytesPerPixel) const
196635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            const int offset = m_coord.x() * bytesPerPixel;
198635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            switch (bytesPerPixel) {
199635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            case 2:
2000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return readUint16(offset);
201635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
202635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            case 3: {
2030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // It doesn't matter that we never set the most significant byte
2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // of the return value here in little-endian mode, the caller
2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // won't read it.
206635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                uint32_t pixel;
2070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3);
208d0825bca7fe65beaee391d30da42e937db621564Steve Block        #if CPU(BIG_ENDIAN)
209692e5dbf12901edacf14812a6fae25462920af42Steve Block                pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24);
210635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        #endif
211635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                return pixel;
212635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
213635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
214635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            case 4:
2150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return readUint32(offset);
216635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
217635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            default:
218635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                ASSERT_NOT_REACHED();
219635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                return 0;
220635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
221635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A)
2240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // in the given pixel data.
225635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inline unsigned getComponent(uint32_t pixel, int component) const
226635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
227692e5dbf12901edacf14812a6fae25462920af42Steve Block            return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component]) << m_bitShiftsLeft[component];
228635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
229635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
230635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inline unsigned getAlpha(uint32_t pixel) const
231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
232635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // For images without alpha, return alpha of 0xff.
233692e5dbf12901edacf14812a6fae25462920af42Steve Block            return m_bitMasks[3] ? getComponent(pixel, 3) : 0xff;
234635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
235635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Sets the current pixel to the color given by |colorIndex|.  This also
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // increments the relevant local variables to move the current pixel
2380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // right by one.
239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        inline void setI(size_t colorIndex)
240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
241692e5dbf12901edacf14812a6fae25462920af42Steve Block            setRGBA(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff);
242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Like setI(), but with the individual component values specified.
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        inline void setRGBA(unsigned red,
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            unsigned green,
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            unsigned blue,
2480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                            unsigned alpha)
249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
250692e5dbf12901edacf14812a6fae25462920af42Steve Block            m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue, alpha);
251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_coord.move(1, 0);
252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Fills pixels from the current X-coordinate up to, but not including,
2550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // |endCoord| with the color given by the individual components.  This
2560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // also increments the relevant local variables to move the current
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // pixel right to |endCoord|.
2580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        inline void fillRGBA(int endCoord,
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                             unsigned red,
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                             unsigned green,
2610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                             unsigned blue,
2620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                             unsigned alpha)
263635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        {
264635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            while (m_coord.x() < endCoord)
265635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                setRGBA(red, green, blue, alpha);
266635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
267635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Resets the relevant local variables to start drawing at the left edge
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // of the "next" row, where "next" is above or below the current row
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // depending on the value of |m_isTopDown|.
271635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        void moveBufferToNextRow();
272635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The decoder that owns us.
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ImageDecoder* m_parent;
2750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The destination for the pixel data.
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        ImageFrame* m_buffer;
2780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The file to decode.
2800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        RefPtr<SharedBuffer> m_data;
2810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // An index into |m_data| representing how much we've already decoded.
2830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        size_t m_decodedOffset;
2840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The file offset at which the BMP info header starts.
2860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        size_t m_headerOffset;
2870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The file offset at which the actual image bits start.  When decoding
2890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // ICO files, this is set to 0, since it's not stored anywhere in a
2900bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // header; the reader functions expect the image data to start
2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // immediately after the header and (if necessary) color table.
2920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        size_t m_imgDataOffset;
2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The BMP info header.
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        BitmapInfoHeader m_infoHeader;
296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // True if this is an OS/2 1.x (aka Windows 2.x) BMP.  The struct
2980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // layouts for this type of BMP are slightly different from the later,
2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // more common formats.
300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_isOS21x;
301635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // True if this is an OS/2 2.x BMP.  The meanings of compression types 3
303635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // and 4 for this type of BMP differ from Windows V3+ BMPs.
304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // This will be falsely negative in some cases, but only ones where the
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // way we misinterpret the data is irrelevant.
307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_isOS22x;
308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
309635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // True if the BMP is not vertically flipped, that is, the first line of
310635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // raster data in the file is the top line of the image.
311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_isTopDown;
312635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // These flags get set to false as we finish each processing stage.
314635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_needToProcessBitmasks;
315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_needToProcessColorTable;
316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Masks/offsets for the color values for non-palette formats.  These
3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // are bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B,
3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // A.
320635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        //
321635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The right/left shift values are meant to be applied after the masks.
3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // We need to right shift to compensate for the bitfields' offsets into
3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // the 32 bits of pixel data, and left shift to scale the color values
3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // up for fields with less than 8 bits of precision.  Sadly, we can't
3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // just combine these into one shift value because the net shift amount
3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // could go either direction.  (If only "<< -x" were equivalent to
3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // ">> x"...)
328635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        uint32_t m_bitMasks[4];
329635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int m_bitShiftsRight[4];
330635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        int m_bitShiftsLeft[4];
331635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
332635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The color palette, for paletted formats.
333635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        size_t m_tableSizeInBytes;
334635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        Vector<RGBTriple> m_colorTable;
335635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
336635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The coordinate to which we've decoded the image.
337635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        IntPoint m_coord;
338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
339635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Variables that track whether we've seen pixels with alpha values != 0
340635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // and == 0, respectively.  See comments in processNonRLEData() on how
341635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // these are used.
342635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_seenNonZeroAlphaPixel;
343635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        bool m_seenZeroAlphaPixel;
3440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // ICOs store a 1bpp "mask" immediately after the main bitmap image data
3460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // (and, confusingly, add its height to the biHeight value in the info
3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // header, thus doubling it).  This variable tracks whether we have such
3480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // a mask and if we've started decoding it yet.
3490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        AndMaskState m_andMaskState;
350635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    };
351635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project} // namespace WebCore
353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
354635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#endif
355