1 /* 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef ICOImageDecoder_h 32 #define ICOImageDecoder_h 33 34 #include "BMPImageReader.h" 35 36 namespace WebCore { 37 38 class PNGImageDecoder; 39 40 // This class decodes the ICO and CUR image formats. 41 class ICOImageDecoder : public ImageDecoder { 42 public: 43 ICOImageDecoder(); 44 virtual ~ICOImageDecoder(); 45 46 // ImageDecoder filenameExtension()47 virtual String filenameExtension() const { return "ico"; } 48 virtual void setData(SharedBuffer*, bool allDataReceived); 49 virtual bool isSizeAvailable(); 50 virtual IntSize size() const; 51 virtual IntSize frameSizeAtIndex(size_t) const; 52 virtual bool setSize(unsigned width, unsigned height); 53 virtual size_t frameCount(); 54 virtual RGBA32Buffer* frameBufferAtIndex(size_t); 55 56 private: 57 enum ImageType { 58 Unknown, 59 BMP, 60 PNG, 61 }; 62 63 struct IconDirectoryEntry { 64 IntSize m_size; 65 uint16_t m_bitCount; 66 uint32_t m_imageOffset; 67 }; 68 69 // Returns true if |a| is a preferable icon entry to |b|. 70 // Larger sizes, or greater bitdepths at the same size, are preferable. 71 static bool compareEntries(const IconDirectoryEntry& a, 72 const IconDirectoryEntry& b); 73 readUint16(int offset)74 inline uint16_t readUint16(int offset) const 75 { 76 return BMPImageReader::readUint16(m_data.get(), 77 m_decodedOffset + offset); 78 } 79 readUint32(int offset)80 inline uint32_t readUint32(int offset) const 81 { 82 return BMPImageReader::readUint32(m_data.get(), 83 m_decodedOffset + offset); 84 } 85 86 // If the desired PNGImageDecoder exists, gives it the appropriate data. 87 void setDataForPNGDecoderAtIndex(size_t); 88 89 // Decodes the entry at |index|. If |onlySize| is true, stops decoding 90 // after calculating the image size. If decoding fails but there is no 91 // more data coming, sets the "decode failure" flag. 92 // 93 // NOTE: If the desired entry is a PNG, this doesn't actually trigger 94 // decoding, it merely ensures the decoder is created and ready to 95 // decode. The caller will then call a function on the PNGImageDecoder 96 // that actually triggers decoding. 97 void decodeWithCheckForDataEnded(size_t index, bool onlySize); 98 99 // Decodes the directory and directory entries at the beginning of the 100 // data, and initializes members. Returns true if all decoding 101 // succeeded. Once this returns true, all entries' sizes are known. 102 bool decodeDirectory(); 103 104 // Decodes the specified entry. 105 bool decodeAtIndex(size_t); 106 107 // Processes the ICONDIR at the beginning of the data. Returns true if 108 // the directory could be decoded. 109 bool processDirectory(); 110 111 // Processes the ICONDIRENTRY records after the directory. Keeps the 112 // "best" entry as the one we'll decode. Returns true if the entries 113 // could be decoded. 114 bool processDirectoryEntries(); 115 116 // Reads and returns a directory entry from the current offset into 117 // |data|. 118 IconDirectoryEntry readDirectoryEntry(); 119 120 // Determines whether the desired entry is a BMP or PNG. Returns true 121 // if the type could be determined. 122 ImageType imageTypeAtIndex(size_t); 123 124 // True if we've seen all the data. 125 bool m_allDataReceived; 126 127 // An index into |m_data| representing how much we've already decoded. 128 // Note that this only tracks data _this_ class decodes; once the 129 // BMPImageReader takes over this will not be updated further. 130 size_t m_decodedOffset; 131 132 // The headers for the ICO. 133 typedef Vector<IconDirectoryEntry> IconDirectoryEntries; 134 IconDirectoryEntries m_dirEntries; 135 136 // The image decoders for the various frames. 137 typedef Vector<BMPImageReader*> BMPReaders; 138 BMPReaders m_bmpReaders; 139 typedef Vector<PNGImageDecoder*> PNGDecoders; 140 PNGDecoders m_pngDecoders; 141 142 // Valid only while a BMPImageReader is decoding, this holds the size 143 // for the particular entry being decoded. 144 IntSize m_frameSize; 145 }; 146 147 } // namespace WebCore 148 149 #endif 150