diff options
Diffstat (limited to 'WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp')
-rw-r--r-- | WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp | 230 |
1 files changed, 0 insertions, 230 deletions
diff --git a/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp deleted file mode 100644 index c340896..0000000 --- a/WebCore/platform/image-decoders/skia/ICOImageDecoder.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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" - -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; - -void ICOImageDecoder::decodeImage(SharedBuffer* data) -{ - // Read and process directory. - if ((m_decodedOffset < sizeOfDirectory) && !processDirectory(data)) - return; - - // Read and process directory entries. - if ((m_decodedOffset < (sizeOfDirectory + (m_directory.idCount * sizeOfDirEntry))) - && !processDirectoryEntries(data)) - return; - - // Check if this entry is a PNG; we need 4 bytes to check the magic number. - if (m_imageType == Unknown) { - if (data->size() < (m_dirEntry.dwImageOffset + 4)) - return; - m_imageType = - strncmp(&data->data()[m_dirEntry.dwImageOffset], "\x89PNG", 4) ? - BMP : PNG; - } - - // Decode selected entry. - if (m_imageType == PNG) - decodePNG(data); - else { - // Note that we don't try to limit the bytes we give to the decoder to - // just the size specified in the icon directory. If the size given in - // the directory is insufficient to decode the whole image, the image is - // corrupt anyway, so whatever we do may be wrong. The easiest choice - // (which we do here) is to simply aggressively consume bytes until we - // run out of bytes, finish decoding, or hit a sequence that makes the - // decoder fail. - decodeBMP(data); - } -} - -RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index) -{ - return (m_imageType == PNG) ? m_pngDecoder.frameBufferAtIndex(0) : - BMPImageReader::frameBufferAtIndex(0); -} - -bool ICOImageDecoder::isSizeAvailable() const -{ - return (m_imageType == PNG) ? m_pngDecoder.isSizeAvailable() : - BMPImageReader::isSizeAvailable(); -} - -IntSize ICOImageDecoder::size() const -{ - return (m_imageType == PNG) ? m_pngDecoder.size() : BMPImageReader::size(); -} - -bool ICOImageDecoder::processDirectory(SharedBuffer* data) -{ - // Read directory. - ASSERT(!m_decodedOffset); - if (data->size() < sizeOfDirectory) - return false; - const uint16_t fileType = readUint16(data, 2); - m_directory.idCount = readUint16(data, 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. - enum { - ICON = 1, - CURSOR = 2, - }; - if (((fileType != ICON) && (fileType != CURSOR)) || - (m_directory.idCount == 0)) - m_failed = true; - - return !m_failed; -} - -bool ICOImageDecoder::processDirectoryEntries(SharedBuffer* data) -{ - // Read directory entries. - ASSERT(m_decodedOffset == sizeOfDirectory); - if ((m_decodedOffset > data->size()) || (data->size() - m_decodedOffset) < - (m_directory.idCount * sizeOfDirEntry)) - return false; - for (int i = 0; i < m_directory.idCount; ++i) { - const IconDirectoryEntry dirEntry = readDirectoryEntry(data); - if ((i == 0) || isBetterEntry(dirEntry)) - m_dirEntry = dirEntry; - } - - // Make sure the specified image offset is past the end of the directory - // entries, and that the offset isn't so large that it overflows when we add - // 4 bytes to it (which we do in decodeImage() while ensuring it's safe to - // examine the first 4 bytes of the image data). - if ((m_dirEntry.dwImageOffset < m_decodedOffset) || - ((m_dirEntry.dwImageOffset + 4) < m_dirEntry.dwImageOffset)) { - m_failed = true; - return false; - } - - // Ready to decode the image at the specified offset. - m_decodedOffset = m_headerOffset = m_dirEntry.dwImageOffset; - return true; -} - -ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry( - SharedBuffer* data) -{ - // Read icon data. - IconDirectoryEntry entry; - entry.bWidth = static_cast<uint8_t>(data->data()[m_decodedOffset]); - if (entry.bWidth == 0) - entry.bWidth = 256; - entry.bHeight = static_cast<uint8_t>(data->data()[m_decodedOffset + 1]); - if (entry.bHeight == 0) - entry.bHeight = 256; - entry.wBitCount = readUint16(data, 6); - entry.dwImageOffset = readUint32(data, 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.wBitCount) { - uint8_t colorCount = data->data()[m_decodedOffset + 2]; - if (colorCount) { - for (--colorCount; colorCount; colorCount >>= 1) - ++entry.wBitCount; - } - } - - m_decodedOffset += sizeOfDirEntry; - return entry; -} - -bool ICOImageDecoder::isBetterEntry(const IconDirectoryEntry& entry) const -{ - const IntSize entrySize(entry.bWidth, entry.bHeight); - const IntSize dirEntrySize(m_dirEntry.bWidth, m_dirEntry.bHeight); - const int entryArea = entry.bWidth * entry.bHeight; - const int dirEntryArea = m_dirEntry.bWidth * m_dirEntry.bHeight; - - if ((entrySize != dirEntrySize) && !m_preferredIconSize.isEmpty()) { - // An icon of exactly the preferred size is best. - if (entrySize == m_preferredIconSize) - return true; - if (dirEntrySize == m_preferredIconSize) - return false; - - // The icon closest to the preferred area without being smaller is - // better. - if (entryArea != dirEntryArea) { - return (entryArea < dirEntryArea) - && (entryArea >= (m_preferredIconSize.width() * m_preferredIconSize.height())); - } - } - - // Larger icons are better. - if (entryArea != dirEntryArea) - return (entryArea > dirEntryArea); - - // Higher bit-depth icons are better. - return (entry.wBitCount > m_dirEntry.wBitCount); -} - -void ICOImageDecoder::decodePNG(SharedBuffer* data) -{ - // Copy out PNG data to a separate vector and instantiate PNG decoder. - // It would be nice to save this copy, if I could figure out how to just - // offset the perceived start of |data| by |m_dirEntry.dwImageOffset| when - // passing it to setData()... - RefPtr<SharedBuffer> pngData( - SharedBuffer::create(&data->data()[m_dirEntry.dwImageOffset], - data->size() - m_dirEntry.dwImageOffset)); - m_pngDecoder.setData(pngData.get(), true); - - // Decode PNG as a side effect of asking for the frame. Strangely, it's - // seemingly unsafe to call decode() or isSizeAvailable() before calling - // this, as this is the only function that enlarges the framebuffer to - // nonzero size, and before this happens any decoded image data is silently - // thrown away and never decoded again (!). - m_pngDecoder.frameBufferAtIndex(0); - m_failed = m_pngDecoder.failed(); - - // Sanity-check that the size is what we expected. - if (isSizeAvailable() && ((size().width() != m_dirEntry.bWidth) || - (size().height() != m_dirEntry.bHeight))) - m_failed = true; -} - -} |