Changeset 46807 in webkit
- Timestamp:
- Aug 5, 2009 12:36:34 PM (15 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 1 deleted
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r46806 r46807 1 2009-08-05 Peter Kasting <pkasting@google.com> 2 3 Reviewed by Eric Seidel. 4 5 https://bugs.webkit.org/show_bug.cgi?id=26460 6 Return multiple icon entries from the ICO decoder as separate frames, 7 sorted by decreasing quality (much like the CG ICO decoder does). 8 9 As a result of this change, we can eliminate the Skia-specific setData() 10 hack that the Chromium port used to select the desired icon size -- now 11 callers can just enumerate the frames and ask for the data from the one 12 they like. 13 14 Under the hood, the ICO decoder now keeps vectors for a number of things 15 (including directory entries and image decoders) where it used to have 16 single members. However, callers (that I have seen) will only request 17 one frame from the icon, so practically there aren't going to be lots of 18 instantiated image decoders. 19 20 * platform/graphics/ImageSource.h: Move |m_decoder| back to private now that Skia no longer needs to access it. 21 * platform/graphics/cairo/ImageSourceCairo.cpp: 22 (WebCore::createDecoder): Remove size argument from ICO decoder instantiation. 23 * platform/graphics/skia/ImageSourceSkia.cpp: 24 (WebCore::createDecoder): Remove size argument from ICO decoder instantiation. 25 (WebCore::ImageSource::setData): Remove function to ask for a particular icon size. 26 * platform/graphics/skia/ImageSourceSkia.h: Removed. 27 * platform/graphics/wx/ImageSourceWx.cpp: 28 (WebCore::createDecoder): Remove size argument from ICO decoder instantiation. 29 * platform/image-decoders/ico/ICOImageDecoder.cpp: 30 (WebCore::ICOImageDecoder::ICOImageDecoder): 31 (WebCore::ICOImageDecoder::~ICOImageDecoder): Delete all instantiated per-frame decoders. 32 (WebCore::ICOImageDecoder::setData): Send data to all instantiated per-frame decoders. 33 (WebCore::ICOImageDecoder::isSizeAvailable): Use size from icon directory instead of PNG decoder (if applicable) so we can report it without decoding the PNG frames. 34 (WebCore::ICOImageDecoder::size): Report frame-specific size if BMP decoder is calling. Otherwise, use size from icon directory instead of PNG decoder (if applicable). 35 (WebCore::ICOImageDecoder::frameSizeAtIndex): Implement. 36 (WebCore::ICOImageDecoder::setSize): Sanity check value if BMP decoder is calling. 37 (WebCore::ICOImageDecoder::frameCount): Implement. 38 (WebCore::ICOImageDecoder::frameBufferAtIndex): Sanity check size for PNG frames. 39 (WebCore::ICOImageDecoder::compareEntries): Add utility function for sorting entries. 40 (WebCore::ICOImageDecoder::setDataForPNGDecoderAtIndex): Factor out utility function for passing correct data blob to a PNG decoder. 41 (WebCore::ICOImageDecoder::decodeWithCheckForDataEnded): Split decode() into two pieces. 42 (WebCore::ICOImageDecoder::decodeDirectory): The first part of the old decode(). 43 (WebCore::ICOImageDecoder::decodeAtIndex): The second part of the old decode(), split off so we avoid decoding an entry until it's requested. 44 (WebCore::ICOImageDecoder::processDirectory): Add resizing of internal data structures based on directory contents. 45 (WebCore::ICOImageDecoder::processDirectoryEntries): Sort entries by quality. 46 (WebCore::ICOImageDecoder::imageTypeAtIndex): Return type to caller instead of setting a member. 47 * platform/image-decoders/ico/ICOImageDecoder.h: 48 1 49 2009-08-05 Szabo Carol <carol.szabo@nokia.com> 2 50 -
trunk/WebCore/platform/graphics/ImageSource.h
r46590 r46807 143 143 bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded. 144 144 145 // FIXME: This is protected only to allow ImageSourceSkia to set ICO decoder 146 // with a preferred size. See ImageSourceSkia.h for discussion. 147 protected: 145 private: 148 146 NativeImageSourcePtr m_decoder; 149 147 }; -
trunk/WebCore/platform/graphics/cairo/ImageSourceCairo.cpp
r46738 r46807 76 76 if (!memcmp(contents, "\000\000\001\000", 4) || 77 77 !memcmp(contents, "\000\000\002\000", 4)) 78 return new ICOImageDecoder( IntSize());78 return new ICOImageDecoder(); 79 79 80 80 // XBMs require 8 bytes of info. -
trunk/WebCore/platform/graphics/skia/ImageSourceSkia.cpp
r46738 r46807 31 31 32 32 #include "config.h" 33 #include "ImageSource Skia.h"33 #include "ImageSource.h" 34 34 #include "SharedBuffer.h" 35 35 … … 45 45 namespace WebCore { 46 46 47 ImageDecoder* createDecoder(const Vector<char>& data , const IntSize& preferredIconSize)47 ImageDecoder* createDecoder(const Vector<char>& data) 48 48 { 49 49 // We need at least 4 bytes to figure out what kind of image we're dealing with. … … 80 80 if (!memcmp(contents, "\000\000\001\000", 4) || 81 81 !memcmp(contents, "\000\000\002\000", 4)) 82 return new ICOImageDecoder( preferredIconSize);82 return new ICOImageDecoder(); 83 83 84 84 // XBMs require 8 bytes of info. … … 125 125 // made. 126 126 if (!m_decoder) 127 m_decoder = createDecoder(data->buffer() , IntSize());127 m_decoder = createDecoder(data->buffer()); 128 128 129 129 // CreateDecoder will return NULL if the decoder could not be created. Plus, … … 231 231 } 232 232 233 void ImageSourceSkia::setData(SharedBuffer* data,234 bool allDataReceived,235 const IntSize& preferredIconSize)236 {237 if (!m_decoder)238 m_decoder = createDecoder(data->buffer(), preferredIconSize);239 240 ImageSource::setData(data, allDataReceived);241 }242 243 233 String ImageSource::filenameExtension() const 244 234 { -
trunk/WebCore/platform/graphics/wx/ImageSourceWx.cpp
r46738 r46807 81 81 if (!memcmp(contents, "\000\000\001\000", 4) || 82 82 !memcmp(contents, "\000\000\002\000", 4)) 83 return new ICOImageDecoder( IntSize());83 return new ICOImageDecoder(); 84 84 85 85 // XBMs require 8 bytes of info. -
trunk/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
r44874 r46807 32 32 #include "ICOImageDecoder.h" 33 33 34 #include <algorithm> 35 34 36 #include "BMPImageReader.h" 35 37 #include "PNGImageDecoder.h" … … 43 45 static const size_t sizeOfDirEntry = 16; 44 46 45 ICOImageDecoder::ICOImageDecoder( const IntSize& preferredIconSize)47 ICOImageDecoder::ICOImageDecoder() 46 48 : ImageDecoder() 47 49 , m_allDataReceived(false) 48 50 , m_decodedOffset(0) 49 , m_preferredIconSize(preferredIconSize) 50 , m_imageType(Unknown) 51 { 51 { 52 } 53 54 ICOImageDecoder::~ICOImageDecoder() 55 { 56 deleteAllValues(m_bmpReaders); 57 deleteAllValues(m_pngDecoders); 52 58 } 53 59 … … 59 65 ImageDecoder::setData(data, allDataReceived); 60 66 m_allDataReceived = allDataReceived; 61 if (m_bmpReader) 62 m_bmpReader->setData(data); 63 if (m_pngDecoder) { 64 // Copy out PNG data to a separate vector and send to the PNG decoder. 65 // FIXME: Save this copy by making the PNG decoder able to take an 66 // optional offset. 67 RefPtr<SharedBuffer> pngData( 68 SharedBuffer::create(&m_data->data()[m_dirEntry.dwImageOffset], 69 m_data->size() - m_dirEntry.dwImageOffset)); 70 m_pngDecoder->setData(pngData.get(), m_allDataReceived); 71 } 67 68 for (BMPReaders::iterator i(m_bmpReaders.begin()); 69 i != m_bmpReaders.end(); ++i) { 70 if (*i) 71 (*i)->setData(data); 72 } 73 for (size_t i = 0; i < m_pngDecoders.size(); ++i) 74 setDataForPNGDecoderAtIndex(i); 72 75 } 73 76 74 77 bool ICOImageDecoder::isSizeAvailable() 75 78 { 76 if (!ImageDecoder::isSizeAvailable() && !failed()) 77 decodeWithCheckForDataEnded(true); 78 79 return (m_imageType == PNG) ? 80 m_pngDecoder->isSizeAvailable() : ImageDecoder::isSizeAvailable(); 79 if (!ImageDecoder::isSizeAvailable()) 80 decodeWithCheckForDataEnded(0, true); 81 82 return ImageDecoder::isSizeAvailable(); 81 83 } 82 84 83 85 IntSize ICOImageDecoder::size() const 84 86 { 85 return (m_imageType == PNG) ? m_pngDecoder->size() : ImageDecoder::size(); 87 return m_frameSize.isEmpty() ? ImageDecoder::size() : m_frameSize; 88 } 89 90 IntSize ICOImageDecoder::frameSizeAtIndex(size_t index) const 91 { 92 return (index && (index < m_dirEntries.size())) ? 93 m_dirEntries[index].m_size : size(); 94 } 95 96 bool ICOImageDecoder::setSize(unsigned width, unsigned height) 97 { 98 if (m_frameSize.isEmpty()) 99 return ImageDecoder::setSize(width, height); 100 101 // The size calculated inside the BMPImageReader had better match the one in 102 // the icon directory. 103 if ((width != m_frameSize.width()) || (height != m_frameSize.height())) 104 setFailed(); 105 return !failed(); 106 } 107 108 size_t ICOImageDecoder::frameCount() 109 { 110 decodeWithCheckForDataEnded(0, true); 111 if (m_frameBufferCache.isEmpty()) 112 m_frameBufferCache.resize(m_dirEntries.size()); 113 // CAUTION: We must not resize m_frameBufferCache again after this, as 114 // decodeAtIndex() may give a BMPImageReader a pointer to one of the 115 // entries. 116 return m_frameBufferCache.size(); 86 117 } 87 118 88 119 RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index) 89 120 { 90 if (index) 121 // Ensure |index| is valid. 122 if (index >= frameCount()) 91 123 return 0; 92 124 93 if (m_imageType == Unknown) 94 decodeWithCheckForDataEnded(true); 95 96 if (m_imageType == PNG) { 97 m_frameBufferCache.clear(); 98 return m_pngDecoder->frameBufferAtIndex(index); 99 } 100 101 if (m_frameBufferCache.isEmpty()) 102 m_frameBufferCache.resize(1); 103 104 RGBA32Buffer* buffer = &m_frameBufferCache.first(); 105 if (buffer->status() != RGBA32Buffer::FrameComplete && (m_imageType == BMP) 106 && !failed()) 107 decodeWithCheckForDataEnded(false); 108 return buffer; 109 } 110 111 void ICOImageDecoder::decodeWithCheckForDataEnded(bool onlySize) 125 // Determine the image type, and if this is a BMP, decode. 126 decodeWithCheckForDataEnded(index, false); 127 128 // PNGs decode into their own framebuffers, so only use our internal cache 129 // for non-PNGs (BMP or unknown). 130 if (!m_pngDecoders[index]) 131 return &m_frameBufferCache[index]; 132 133 // Fail if the size the PNGImageDecoder calculated does not match the size 134 // in the directory. 135 if (m_pngDecoders[index]->isSizeAvailable()) { 136 const IntSize pngSize(m_pngDecoders[index]->size()); 137 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; 138 if (pngSize != dirEntry.m_size) { 139 setFailed(); 140 m_pngDecoders[index]->setFailed(); 141 } 142 } 143 144 return m_pngDecoders[index]->frameBufferAtIndex(0); 145 } 146 147 // static 148 bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, 149 const IconDirectoryEntry& b) 150 { 151 // Larger icons are better. 152 const int aEntryArea = a.m_size.width() * a.m_size.height(); 153 const int bEntryArea = b.m_size.width() * b.m_size.height(); 154 if (aEntryArea != bEntryArea) 155 return (aEntryArea > bEntryArea); 156 157 // Higher bit-depth icons are better. 158 return (a.m_bitCount > b.m_bitCount); 159 } 160 161 void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) 162 { 163 if (!m_pngDecoders[index]) 164 return; 165 166 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; 167 // Copy out PNG data to a separate vector and send to the PNG decoder. 168 // FIXME: Save this copy by making the PNG decoder able to take an 169 // optional offset. 170 RefPtr<SharedBuffer> pngData( 171 SharedBuffer::create(&m_data->data()[dirEntry.m_imageOffset], 172 m_data->size() - dirEntry.m_imageOffset)); 173 m_pngDecoders[index]->setData(pngData.get(), m_allDataReceived); 174 } 175 176 void ICOImageDecoder::decodeWithCheckForDataEnded(size_t index, bool onlySize) 112 177 { 113 178 if (failed()) … … 116 181 // If we couldn't decode the image but we've received all the data, decoding 117 182 // has failed. 118 if (!decode(onlySize) && m_allDataReceived) 183 if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) 184 && m_allDataReceived) 119 185 setFailed(); 120 186 } 121 187 122 bool ICOImageDecoder::decode (bool onlySize)188 bool ICOImageDecoder::decodeDirectory() 123 189 { 124 190 // Read and process directory. … … 127 193 128 194 // Read and process directory entries. 129 if ((m_decodedOffset < 130 (sizeOfDirectory + (m_directory.idCount * sizeOfDirEntry))) 131 && !processDirectoryEntries()) 132 return false; 133 134 // Get the image type. 135 if ((m_imageType == Unknown) && !processImageType()) 136 return false; 137 138 // Create the appropriate image decoder if need be. 139 if ((m_imageType == PNG) ? !m_pngDecoder : !m_bmpReader) { 140 if (m_imageType == PNG) 141 m_pngDecoder.set(new PNGImageDecoder()); 142 else 143 m_bmpReader.set(new BMPImageReader(this, m_decodedOffset, 0, true)); 144 145 // Note that we don't try to limit the bytes we give to the decoder to 146 // just the size specified in the icon directory. If the size given in 147 // the directory is insufficient to decode the whole image, the image is 148 // corrupt anyway, so whatever we do may be wrong. The easiest choice 149 // (which we do here) is to simply aggressively consume bytes until we 150 // run out of bytes, finish decoding, or hit a sequence that makes the 151 // decoder fail. 152 setData(m_data.get(), m_allDataReceived); 195 return (m_decodedOffset >= 196 (sizeOfDirectory + (m_dirEntries.size() * sizeOfDirEntry))) 197 || processDirectoryEntries(); 198 } 199 200 bool ICOImageDecoder::decodeAtIndex(size_t index) 201 { 202 ASSERT(index < m_dirEntries.size()); 203 const IconDirectoryEntry& dirEntry = m_dirEntries[index]; 204 if (!m_bmpReaders[index] && !m_pngDecoders[index]) { 205 // Image type unknown. 206 const ImageType imageType = imageTypeAtIndex(index); 207 if (imageType == BMP) { 208 // We need to have already sized m_frameBufferCache before this, and 209 // we must not resize it again later (see caution in frameCount()). 210 ASSERT(m_frameBufferCache.size() == m_dirEntries.size()); 211 m_bmpReaders[index] = 212 new BMPImageReader(this, dirEntry.m_imageOffset, 0, true); 213 m_bmpReaders[index]->setData(m_data.get()); 214 m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); 215 } else if (imageType == PNG) { 216 m_pngDecoders[index] = new PNGImageDecoder(); 217 setDataForPNGDecoderAtIndex(index); 218 } else { 219 // Not enough data to determine image type yet. 220 return false; 221 } 222 } 223 224 if (m_bmpReaders[index]) { 225 m_frameSize = dirEntry.m_size; 226 bool result = m_bmpReaders[index]->decodeBMP(false); 227 m_frameSize = IntSize(); 228 return result; 153 229 } 154 230 155 231 // For PNGs, we're now done; further decoding will happen when calling 156 // isSizeAvailable() or frameBufferAtIndex() on the PNG decoder. 157 if (m_imageType == PNG) 158 return true; 159 160 if (!m_frameBufferCache.isEmpty()) 161 m_bmpReader->setBuffer(&m_frameBufferCache.first()); 162 163 return m_bmpReader->decodeBMP(onlySize); 232 // frameBufferAtIndex() on the PNG decoder. 233 return true; 164 234 } 165 235 … … 171 241 return false; 172 242 const uint16_t fileType = readUint16(2); 173 m_directory.idCount = readUint16(4);243 const uint16_t idCount = readUint16(4); 174 244 m_decodedOffset = sizeOfDirectory; 175 245 … … 180 250 CURSOR = 2, 181 251 }; 182 if (((fileType != ICON) && (fileType != CURSOR)) || 183 (m_directory.idCount == 0)) 252 if (((fileType != ICON) && (fileType != CURSOR)) || (idCount == 0)) { 184 253 setFailed(); 185 186 return !failed(); 254 return false; 255 } 256 257 // Enlarge member vectors to hold all the entries. We must initialize the 258 // BMP and PNG decoding vectors to 0 so that all entries can be safely 259 // deleted in our destructor. If we don't do this, they'll contain garbage 260 // values, and deleting those will corrupt memory. 261 m_dirEntries.resize(idCount); 262 m_bmpReaders.fill(0, idCount); 263 m_pngDecoders.fill(0, idCount); 264 return true; 187 265 } 188 266 … … 193 271 if ((m_decodedOffset > m_data->size()) 194 272 || ((m_data->size() - m_decodedOffset) < 195 (m_dir ectory.idCount* sizeOfDirEntry)))273 (m_dirEntries.size() * sizeOfDirEntry))) 196 274 return false; 197 for (int i = 0; i < m_directory.idCount; ++i) { 198 const IconDirectoryEntry dirEntry = readDirectoryEntry(); 199 if ((i == 0) || isBetterEntry(dirEntry)) 200 m_dirEntry = dirEntry; 201 } 202 203 // Make sure the specified image offset is past the end of the directory 204 // entries, and that the offset isn't so large that it overflows when we add 205 // 4 bytes to it (which we do in decodeImage() while ensuring it's safe to 206 // examine the first 4 bytes of the image data). 207 if ((m_dirEntry.dwImageOffset < m_decodedOffset) || 208 ((m_dirEntry.dwImageOffset + 4) < m_dirEntry.dwImageOffset)) { 209 setFailed(); 210 return false; 211 } 212 213 // Ready to decode the image at the specified offset. 214 m_decodedOffset = m_dirEntry.dwImageOffset; 275 for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); 276 i != m_dirEntries.end(); ++i) 277 *i = readDirectoryEntry(); // Updates m_decodedOffset. 278 279 // Make sure the specified image offsets are past the end of the directory 280 // entries. 281 for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); 282 i != m_dirEntries.end(); ++i) { 283 if (i->m_imageOffset < m_decodedOffset) { 284 setFailed(); 285 return false; 286 } 287 } 288 289 // Arrange frames in decreasing quality order. 290 std::sort(m_dirEntries.begin(), m_dirEntries.end(), compareEntries); 291 292 // The image size is the size of the largest entry. 293 const IconDirectoryEntry& dirEntry = m_dirEntries.first(); 294 setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); 215 295 return true; 216 296 } … … 219 299 { 220 300 // Read icon data. 301 // The casts to uint8_t in the next few lines are because that's the on-disk 302 // type of the width and height values. Storing them in ints (instead of 303 // matching uint8_ts) is so we can record dimensions of size 256 (which is 304 // what a zero byte really means). 305 int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]); 306 if (width == 0) 307 width = 256; 308 int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]); 309 if (height == 0) 310 height = 256; 221 311 IconDirectoryEntry entry; 222 entry.bWidth = static_cast<uint8_t>(m_data->data()[m_decodedOffset]); 223 if (entry.bWidth == 0) 224 entry.bWidth = 256; 225 entry.bHeight = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]); 226 if (entry.bHeight == 0) 227 entry.bHeight = 256; 228 entry.wBitCount = readUint16(6); 229 entry.dwImageOffset = readUint32(12); 312 entry.m_size = IntSize(width, height); 313 entry.m_bitCount = readUint16(6); 314 entry.m_imageOffset = readUint32(12); 230 315 231 316 // Some icons don't have a bit depth, only a color count. Convert the … … 233 318 // this isn't quite what the bitmap info header says later, as we only use 234 319 // this value to determine which icon entry is best. 235 if (!entry. wBitCount) {320 if (!entry.m_bitCount) { 236 321 uint8_t colorCount = m_data->data()[m_decodedOffset + 2]; 237 322 if (colorCount) { 238 323 for (--colorCount; colorCount; colorCount >>= 1) 239 ++entry. wBitCount;324 ++entry.m_bitCount; 240 325 } 241 326 } … … 245 330 } 246 331 247 bool ICOImageDecoder::isBetterEntry(const IconDirectoryEntry& entry) const 248 { 249 const IntSize entrySize(entry.bWidth, entry.bHeight); 250 const IntSize dirEntrySize(m_dirEntry.bWidth, m_dirEntry.bHeight); 251 const int entryArea = entry.bWidth * entry.bHeight; 252 const int dirEntryArea = m_dirEntry.bWidth * m_dirEntry.bHeight; 253 254 if ((entrySize != dirEntrySize) && !m_preferredIconSize.isEmpty()) { 255 // An icon of exactly the preferred size is best. 256 if (entrySize == m_preferredIconSize) 257 return true; 258 if (dirEntrySize == m_preferredIconSize) 259 return false; 260 261 // The icon closest to the preferred area without being smaller is 262 // better. 263 if (entryArea != dirEntryArea) { 264 return (entryArea < dirEntryArea) && (entryArea >= 265 (m_preferredIconSize.width() * m_preferredIconSize.height())); 266 } 267 } 268 269 // Larger icons are better. 270 if (entryArea != dirEntryArea) 271 return (entryArea > dirEntryArea); 272 273 // Higher bit-depth icons are better. 274 return (entry.wBitCount > m_dirEntry.wBitCount); 275 } 276 277 bool ICOImageDecoder::processImageType() 332 ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index) 278 333 { 279 334 // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic 280 335 // number. 281 ASSERT(m_decodedOffset == m_dirEntry.dwImageOffset); 282 if ((m_decodedOffset > m_data->size()) 283 || ((m_data->size() - m_decodedOffset) < 4)) 284 return false; 285 m_imageType = 286 strncmp(&m_data->data()[m_decodedOffset], "\x89PNG", 4) ? BMP : PNG; 287 return true; 288 } 289 290 } 336 ASSERT(index < m_dirEntries.size()); 337 const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; 338 if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) 339 return Unknown; 340 return strncmp(&m_data->data()[imageOffset], "\x89PNG", 4) ? BMP : PNG; 341 } 342 343 } -
trunk/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
r44874 r46807 41 41 class ICOImageDecoder : public ImageDecoder { 42 42 public: 43 // See comments on |m_preferredIconSize| below.44 ICOImageDecoder(const IntSize& preferredIconSize);43 ICOImageDecoder(); 44 virtual ~ICOImageDecoder(); 45 45 46 46 // ImageDecoder … … 49 49 virtual bool isSizeAvailable(); 50 50 virtual IntSize size() const; 51 virtual RGBA32Buffer* frameBufferAtIndex(size_t index); 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); 52 55 53 56 private: … … 58 61 }; 59 62 60 // These are based on the Windows ICONDIR and ICONDIRENTRY structs, but61 // with unnecessary entries removed.62 struct IconDirectory {63 uint 16_t idCount;63 struct IconDirectoryEntry { 64 IntSize m_size; 65 uint16_t m_bitCount; 66 uint32_t m_imageOffset; 64 67 }; 65 struct IconDirectoryEntry { 66 uint16_t bWidth; // 16 bits so we can represent 256 as 256, not 0 67 uint16_t bHeight; // " 68 uint16_t wBitCount; 69 uint32_t dwImageOffset; 70 }; 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); 71 73 72 74 inline uint16_t readUint16(int offset) const … … 82 84 } 83 85 84 // Decodes the image. If |onlySize| is true, stops decoding after 85 // calculating the image size. If decoding fails but there is no more 86 // data coming, sets the "decode failure" flag. 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. 87 92 // 88 93 // NOTE: If the desired entry is a PNG, this doesn't actually trigger … … 90 95 // decode. The caller will then call a function on the PNGImageDecoder 91 96 // that actually triggers decoding. 92 void decodeWithCheckForDataEnded( bool onlySize);97 void decodeWithCheckForDataEnded(size_t index, bool onlySize); 93 98 94 // Decodes the image. If |onlySize| is true, stops decoding after 95 // calculating the image size. Returns whether decoding succeeded. 96 // NOTE: Used internally by decodeWithCheckForDataEnded(). Other people 97 // should not call this. 98 bool decode(bool onlySize); 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); 99 106 100 107 // Processes the ICONDIR at the beginning of the data. Returns true if … … 111 118 IconDirectoryEntry readDirectoryEntry(); 112 119 113 // Returns true if |entry| is a preferable icon entry to m_dirEntry.114 // Larger sizes, or greater bitdepths at the same size, are preferable.115 bool isBetterEntry(const IconDirectoryEntry&) const;116 117 120 // Determines whether the desired entry is a BMP or PNG. Returns true 118 121 // if the type could be determined. 119 bool processImageType();122 ImageType imageTypeAtIndex(size_t); 120 123 121 124 // True if we've seen all the data. … … 127 130 size_t m_decodedOffset; 128 131 129 // The entry size we should prefer. If this is empty, we choose the 130 // largest available size. If no entries of the desired size are 131 // available, we pick the next larger size. 132 IntSize m_preferredIconSize; 132 // The headers for the ICO. 133 typedef Vector<IconDirectoryEntry> IconDirectoryEntries; 134 IconDirectoryEntries m_dirEntries; 133 135 134 // The headers for the ICO. 135 IconDirectory m_directory; 136 IconDirectoryEntry m_dirEntry; 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; 137 141 138 // The BMP reader, if we need to use one. 139 OwnPtr<BMPImageReader> m_bmpReader; 140 141 // The PNG decoder, if we need to use one. 142 OwnPtr<PNGImageDecoder> m_pngDecoder; 143 144 // What kind of image data is stored at the entry we're decoding. 145 ImageType m_imageType; 142 // Valid only while a BMPImageReader is decoding, this holds the size 143 // for the particular entry being decoded. 144 IntSize m_frameSize; 146 145 }; 147 146
Note: See TracChangeset
for help on using the changeset viewer.