diff options
Diffstat (limited to 'WebCore/platform/image-decoders')
25 files changed, 0 insertions, 6083 deletions
diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp deleted file mode 100644 index 8491da9..0000000 --- a/WebCore/platform/image-decoders/ImageDecoder.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2008-2009 Torch Mobile, Inc. - * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include "ImageDecoder.h" - -#include <algorithm> -#include <cmath> - -#include "BMPImageDecoder.h" -#include "GIFImageDecoder.h" -#include "ICOImageDecoder.h" -#include "JPEGImageDecoder.h" -#include "PNGImageDecoder.h" -#include "WEBPImageDecoder.h" -#include "SharedBuffer.h" - -using namespace std; - -namespace WebCore { - -static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const SharedBuffer& sharedBuffer, unsigned offset) -{ - unsigned bytesExtracted = 0; - const char* moreData; - while (unsigned moreDataLength = sharedBuffer.getSomeData(moreData, offset)) { - unsigned bytesToCopy = min(bufferLength - bytesExtracted, moreDataLength); - memcpy(buffer + bytesExtracted, moreData, bytesToCopy); - bytesExtracted += bytesToCopy; - if (bytesExtracted == bufferLength) - break; - offset += bytesToCopy; - } - return bytesExtracted; -} - -#if !OS(ANDROID) -// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and -// JPEGDecoder, which aren't used on Android, and which don't all compile. -// TODO: Find a better fix. -ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) -{ - // We need at least 4 bytes to figure out what kind of image we're dealing - // with. - static const unsigned maxMarkerLength = 4; - char contents[maxMarkerLength]; - unsigned length = copyFromSharedBuffer(contents, maxMarkerLength, data, 0); - if (length < maxMarkerLength) - return 0; - - // GIFs begin with GIF8(7 or 9). - if (strncmp(contents, "GIF8", 4) == 0) - return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption); - - // Test for PNG. - if (!memcmp(contents, "\x89\x50\x4E\x47", 4)) - return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption); - - // JPEG - if (!memcmp(contents, "\xFF\xD8\xFF", 3)) - return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption); - -#if USE(WEBP) - if (!memcmp(contents, "RIFF", 4)) { - static const unsigned webpExtraMarker = 6; - static const unsigned webpExtraMarkeroffset = 8; - char header[webpExtraMarker]; - unsigned length = copyFromSharedBuffer(header, webpExtraMarker, data, webpExtraMarkeroffset); - if (length >= webpExtraMarker) { - if (!memcmp(header, "WEBPVP", webpExtraMarker)) - return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption); - } - } -#endif - - // BMP - if (strncmp(contents, "BM", 2) == 0) - return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption); - - // ICOs always begin with a 2-byte 0 followed by a 2-byte 1. - // CURs begin with 2-byte 0 followed by 2-byte 2. - if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4)) - return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption); - - // Give up. We don't know what the heck this is. - return 0; -} -#endif // !OS(ANDROID) - -#if !PLATFORM(SKIA) - -RGBA32Buffer::RGBA32Buffer() - : m_hasAlpha(false) - , m_status(FrameEmpty) - , m_duration(0) - , m_disposalMethod(DisposeNotSpecified) - , m_premultiplyAlpha(true) -{ -} - -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) -{ - if (this == &other) - return *this; - - copyReferenceToBitmapData(other); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - setPremultiplyAlpha(other.premultiplyAlpha()); - return *this; -} - -void RGBA32Buffer::clear() -{ - m_backingStore.clear(); - m_bytes = 0; - m_status = FrameEmpty; - // NOTE: Do not reset other members here; clearFrameBufferCache() calls this - // to free the bitmap data, but other functions like initFrameBuffer() and - // frameComplete() may still need to read other metadata out of this frame - // later. -} - -void RGBA32Buffer::zeroFill() -{ - memset(m_bytes, 0, m_size.width() * m_size.height() * sizeof(PixelData)); - m_hasAlpha = true; -} - -#if !PLATFORM(CG) - -void RGBA32Buffer::copyReferenceToBitmapData(const RGBA32Buffer& other) -{ - ASSERT(this != &other); - copyBitmapData(other); -} - -bool RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) -{ - if (this == &other) - return true; - - m_backingStore = other.m_backingStore; - m_bytes = m_backingStore.data(); - m_size = other.m_size; - setHasAlpha(other.m_hasAlpha); - return true; -} - -bool RGBA32Buffer::setSize(int newWidth, int newHeight) -{ - // NOTE: This has no way to check for allocation failure if the requested - // size was too big... - m_backingStore.resize(newWidth * newHeight); - m_bytes = m_backingStore.data(); - m_size = IntSize(newWidth, newHeight); - - // Zero the image. - zeroFill(); - - return true; -} - -#endif - -bool RGBA32Buffer::hasAlpha() const -{ - return m_hasAlpha; -} - -void RGBA32Buffer::setHasAlpha(bool alpha) -{ - m_hasAlpha = alpha; -} - -void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) -{ - m_colorProfile = colorProfile; -} - -void RGBA32Buffer::setStatus(FrameStatus status) -{ - m_status = status; -} - -int RGBA32Buffer::width() const -{ - return m_size.width(); -} - -int RGBA32Buffer::height() const -{ - return m_size.height(); -} - -#endif - -namespace { - -enum MatchType { - Exact, - UpperBound, - LowerBound -}; - -inline void fillScaledValues(Vector<int>& scaledValues, double scaleRate, int length) -{ - double inflateRate = 1. / scaleRate; - scaledValues.reserveCapacity(static_cast<int>(length * scaleRate + 0.5)); - for (int scaledIndex = 0; ; ++scaledIndex) { - int index = static_cast<int>(scaledIndex * inflateRate + 0.5); - if (index >= length) - break; - scaledValues.append(index); - } -} - -template <MatchType type> int getScaledValue(const Vector<int>& scaledValues, int valueToMatch, int searchStart) -{ - if (scaledValues.isEmpty()) - return valueToMatch; - - const int* dataStart = scaledValues.data(); - const int* dataEnd = dataStart + scaledValues.size(); - const int* matched = std::lower_bound(dataStart + searchStart, dataEnd, valueToMatch); - switch (type) { - case Exact: - return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : -1; - case LowerBound: - return matched != dataEnd && *matched == valueToMatch ? matched - dataStart : matched - dataStart - 1; - case UpperBound: - default: - return matched != dataEnd ? matched - dataStart : -1; - } -} - -} - -void ImageDecoder::prepareScaleDataIfNecessary() -{ - m_scaled = false; - m_scaledColumns.clear(); - m_scaledRows.clear(); - - int width = size().width(); - int height = size().height(); - int numPixels = height * width; - if (m_maxNumPixels <= 0 || numPixels <= m_maxNumPixels) - return; - - m_scaled = true; - double scale = sqrt(m_maxNumPixels / (double)numPixels); - fillScaledValues(m_scaledColumns, scale, width); - fillScaledValues(m_scaledRows, scale, height); -} - -int ImageDecoder::upperBoundScaledX(int origX, int searchStart) -{ - return getScaledValue<UpperBound>(m_scaledColumns, origX, searchStart); -} - -int ImageDecoder::lowerBoundScaledX(int origX, int searchStart) -{ - return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart); -} - -int ImageDecoder::upperBoundScaledY(int origY, int searchStart) -{ - return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart); -} - -int ImageDecoder::lowerBoundScaledY(int origY, int searchStart) -{ - return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart); -} - -int ImageDecoder::scaledY(int origY, int searchStart) -{ - return getScaledValue<Exact>(m_scaledRows, origY, searchStart); -} - -} diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h deleted file mode 100644 index c3d73c0..0000000 --- a/WebCore/platform/image-decoders/ImageDecoder.h +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008-2009 Torch Mobile, Inc. - * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. - */ - -#ifndef ImageDecoder_h -#define ImageDecoder_h - -#include "IntRect.h" -#include "ImageSource.h" -#include "PlatformString.h" -#include "SharedBuffer.h" -#include <wtf/Assertions.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -#if PLATFORM(SKIA) -#include "NativeImageSkia.h" -#include "SkColorPriv.h" -#elif PLATFORM(QT) -#include <QPixmap> -#include <QImage> -#endif - -namespace WebCore { - - // FIXME: Do we want better encapsulation? - typedef Vector<char> ColorProfile; - - // The RGBA32Buffer object represents the decoded image data in RGBA32 - // format. This buffer is what all decoders write a single frame into. - // Frames are then instantiated for drawing by being handed this buffer. - class RGBA32Buffer { - public: - enum FrameStatus { FrameEmpty, FramePartial, FrameComplete }; - enum FrameDisposalMethod { - // If you change the numeric values of these, make sure you audit - // all users, as some users may cast raw values to/from these - // constants. - DisposeNotSpecified, // Leave frame in framebuffer - DisposeKeep, // Leave frame in framebuffer - DisposeOverwriteBgcolor, // Clear frame to transparent - DisposeOverwritePrevious, // Clear frame to previous framebuffer - // contents - }; -#if PLATFORM(SKIA) || PLATFORM(QT) - typedef uint32_t PixelData; -#else - typedef unsigned PixelData; -#endif - - RGBA32Buffer(); - - RGBA32Buffer(const RGBA32Buffer& other) { operator=(other); } - - // For backends which refcount their data, this operator doesn't need to - // create a new copy of the image data, only increase the ref count. - RGBA32Buffer& operator=(const RGBA32Buffer& other); - - // Deletes the pixel data entirely; used by ImageDecoder to save memory - // when we no longer need to display a frame and only need its metadata. - void clear(); - - // Zeroes the pixel data in the buffer, setting it to fully-transparent. - void zeroFill(); - - // Creates a new copy of the image data in |other|, so the two images - // can be modified independently. Returns whether the copy succeeded. - bool copyBitmapData(const RGBA32Buffer&); - - // Creates a new reference to the image data in |other|. The two images - // share a common backing store. - void copyReferenceToBitmapData(const RGBA32Buffer&); - - // Copies the pixel data at [(startX, startY), (endX, startY)) to the - // same X-coordinates on each subsequent row up to but not including - // endY. - void copyRowNTimes(int startX, int endX, int startY, int endY) - { - ASSERT(startX < width()); - ASSERT(endX <= width()); - ASSERT(startY < height()); - ASSERT(endY <= height()); - const int rowBytes = (endX - startX) * sizeof(PixelData); - const PixelData* const startAddr = getAddr(startX, startY); - for (int destY = startY + 1; destY < endY; ++destY) - memcpy(getAddr(startX, destY), startAddr, rowBytes); - } - -#if PLATFORM(ANDROID) - NativeImageSkia& bitmap() { return m_bitmap; } - const NativeImageSkia& bitmap() const { return m_bitmap; } -#endif - - // Allocates space for the pixel data. Must be called before any pixels - // are written. Will return true on success, false if the memory - // allocation fails. Calling this multiple times is undefined and may - // leak memory. - bool setSize(int newWidth, int newHeight); - - // To be used by ImageSource::createFrameAtIndex(). Returns a pointer - // to the underlying native image data. This pointer will be owned by - // the BitmapImage and freed in FrameData::clear(). - NativeImagePtr asNewNativeImage() const; - - bool hasAlpha() const; - const IntRect& rect() const { return m_rect; } - FrameStatus status() const { return m_status; } - unsigned duration() const { return m_duration; } - FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } - bool premultiplyAlpha() const { return m_premultiplyAlpha; } - - void setHasAlpha(bool alpha); - void setColorProfile(const ColorProfile&); - void setRect(const IntRect& r) { m_rect = r; } - void setStatus(FrameStatus status); - void setDuration(unsigned duration) { m_duration = duration; } - void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } - void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } - - inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) - { - setRGBA(getAddr(x, y), r, g, b, a); - } - -#if PLATFORM(QT) - void setPixmap(const QPixmap& pixmap); -#endif - - private: -#if PLATFORM(CG) - typedef RetainPtr<CFMutableDataRef> NativeBackingStore; -#else - typedef Vector<PixelData> NativeBackingStore; -#endif - - int width() const; - int height() const; - - inline PixelData* getAddr(int x, int y) - { -#if PLATFORM(SKIA) - return m_bitmap.getAddr32(x, y); -#elif PLATFORM(QT) - m_image = m_pixmap.toImage(); - m_pixmap = QPixmap(); - return reinterpret_cast_ptr<QRgb*>(m_image.scanLine(y)) + x; -#else - return m_bytes + (y * width()) + x; -#endif - } - - inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) - { - if (m_premultiplyAlpha && !a) - *dest = 0; - else { - if (m_premultiplyAlpha && a < 255) { - float alphaPercent = a / 255.0f; - r = static_cast<unsigned>(r * alphaPercent); - g = static_cast<unsigned>(g * alphaPercent); - b = static_cast<unsigned>(b * alphaPercent); - } -#if PLATFORM(ANDROID) - *dest = SkPackARGB32(a, r, g, b); -#else - *dest = (a << 24 | r << 16 | g << 8 | b); -#endif - } - } - -#if PLATFORM(SKIA) - NativeImageSkia m_bitmap; -#elif PLATFORM(QT) - mutable QPixmap m_pixmap; - mutable QImage m_image; - bool m_hasAlpha; - IntSize m_size; -#else - NativeBackingStore m_backingStore; - PixelData* m_bytes; // The memory is backed by m_backingStore. - IntSize m_size; // The size of the buffer. This should be the - // same as ImageDecoder::m_size. - bool m_hasAlpha; // Whether or not any of the pixels in the buffer - // have transparency. - ColorProfile m_colorProfile; -#endif - IntRect m_rect; // The rect of the original specified frame within - // the overall buffer. This will always just be - // the entire buffer except for GIF frames whose - // original rect was smaller than the overall - // image size. - FrameStatus m_status; // Whether or not this frame is completely - // finished decoding. - unsigned m_duration; // The animation delay. - FrameDisposalMethod m_disposalMethod; // What to do with this frame's data when - // initializing the next frame. - bool m_premultiplyAlpha; // Whether to premultiply alpha into R, G, B - // channels; by default it's true. - }; - - // The ImageDecoder class represents a base class for specific image format - // decoders (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode - // into RGBA32 format and the base class manages the RGBA32 frame cache. - // - // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to write - // directly to scaled output buffers by down sampling. Call - // setMaxNumPixels() to specify the biggest size that decoded images can - // have. Image decoders will deflate those images that are bigger than - // m_maxNumPixels. (Not supported by all image decoders yet) - class ImageDecoder : public Noncopyable { - public: - ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : m_scaled(false) - , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) - , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored) - , m_sizeAvailable(false) - , m_maxNumPixels(-1) - , m_isAllDataReceived(false) - , m_failed(false) - { - } - - virtual ~ImageDecoder() {} - - // Factory function to create an ImageDecoder. Ports that subclass - // ImageDecoder can provide their own implementation of this to avoid - // needing to write a dedicated setData() implementation. - static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - - // The the filename extension usually associated with an undecoded image - // of this type. - virtual String filenameExtension() const = 0; - - bool isAllDataReceived() const { return m_isAllDataReceived; } - - virtual void setData(SharedBuffer* data, bool allDataReceived) - { - if (m_failed) - return; - m_data = data; - m_isAllDataReceived = allDataReceived; - } - - // Whether or not the size information has been decoded yet. This - // default implementation just returns true if the size has been set and - // we have not seen a failure. Decoders may want to override this to - // lazily decode enough of the image to get the size. - virtual bool isSizeAvailable() - { - return !m_failed && m_sizeAvailable; - } - - // Returns the size of the image. - virtual IntSize size() const - { - return m_size; - } - - IntSize scaledSize() const - { - return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size(); - } - - // Returns the size of frame |index|. This will only differ from size() - // for formats where different frames are different sizes (namely ICO, - // where each frame represents a different icon within the master file). - // Notably, this does not return different sizes for different GIF - // frames, since while these may be stored as smaller rectangles, during - // decoding they are composited to create a full-size frame. - virtual IntSize frameSizeAtIndex(size_t) const - { - return size(); - } - - // Called by the image decoders to set their decoded size, this also - // checks the size for validity. It will return true if the size was - // set, or false if there is an error. On error, the m_failed flag will - // be set and the caller should immediately stop decoding. - virtual bool setSize(unsigned width, unsigned height) - { - if (isOverSize(width, height)) - return setFailed(); - m_size = IntSize(width, height); - m_sizeAvailable = true; - return true; - } - - // The total number of frames for the image. Classes that support - // multiple frames will scan the image data for the answer if they need - // to (without necessarily decoding all of the individual frames). - virtual size_t frameCount() { return 1; } - - // The number of repetitions to perform for an animation loop. - virtual int repetitionCount() const { return cAnimationNone; } - - // Called to obtain the RGBA32Buffer full of decoded data for rendering. - // The decoder plugin will decode as much of the frame as it can before - // handing back the buffer. - virtual RGBA32Buffer* frameBufferAtIndex(size_t) = 0; - - // Whether or not the underlying image format even supports alpha - // transparency. - virtual bool supportsAlpha() const { return true; } - - void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; } - - // Whether or not the gamma and color profile are applied. - bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; } - - // Sets the "decode failure" flag. For caller convenience (since so - // many callers want to return false after calling this), returns false - // to enable easy tailcalling. Subclasses may override this to also - // clean up any local data. - virtual bool setFailed() - { - m_failed = true; - return false; - } - - bool failed() const { return m_failed; } - - // Wipe out frames in the frame buffer cache before |clearBeforeFrame|, - // assuming this can be done without breaking decoding. Different - // decoders place different restrictions on what frames are safe to - // destroy, so this is left to them to implement. - // For convenience's sake, we provide a default (empty) implementation, - // since in practice only GIFs will ever use this. - virtual void clearFrameBufferCache(size_t clearBeforeFrame) { } - -#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING) - void setMaxNumPixels(int m) { m_maxNumPixels = m; } -#endif - - protected: - void prepareScaleDataIfNecessary(); - int upperBoundScaledX(int origX, int searchStart = 0); - int lowerBoundScaledX(int origX, int searchStart = 0); - int upperBoundScaledY(int origY, int searchStart = 0); - int lowerBoundScaledY(int origY, int searchStart = 0); - int scaledY(int origY, int searchStart = 0); - - RefPtr<SharedBuffer> m_data; // The encoded data. - Vector<RGBA32Buffer> m_frameBufferCache; - ColorProfile m_colorProfile; - bool m_scaled; - Vector<int> m_scaledColumns; - Vector<int> m_scaledRows; - bool m_premultiplyAlpha; - bool m_ignoreGammaAndColorProfile; - - private: - // Some code paths compute the size of the image as "width * height * 4" - // and return it as a (signed) int. Avoid overflow. - static bool isOverSize(unsigned width, unsigned height) - { - // width * height must not exceed (2 ^ 29) - 1, so that we don't - // overflow when we multiply by 4. - unsigned long long total_size = static_cast<unsigned long long>(width) - * static_cast<unsigned long long>(height); - return total_size > ((1 << 29) - 1); - } - - IntSize m_size; - bool m_sizeAvailable; - int m_maxNumPixels; - bool m_isAllDataReceived; - bool m_failed; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp deleted file mode 100644 index 220a1ed..0000000 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp +++ /dev/null @@ -1,151 +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 "BMPImageDecoder.h" - -#include "BMPImageReader.h" - -namespace WebCore { - -// Number of bits in .BMP used to store the file header (doesn't match -// "sizeof(BMPImageDecoder::BitmapFileHeader)" since we omit some fields and -// don't pack). -static const size_t sizeOfFileHeader = 14; - -BMPImageDecoder::BMPImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) - , m_decodedOffset(0) -{ -} - -void BMPImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - if (failed()) - return; - - ImageDecoder::setData(data, allDataReceived); - if (m_reader) - m_reader->setData(data); -} - -bool BMPImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(true); - - return ImageDecoder::isSizeAvailable(); -} - -RGBA32Buffer* BMPImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index) - return 0; - - if (m_frameBufferCache.isEmpty()) { - m_frameBufferCache.resize(1); - m_frameBufferCache.first().setPremultiplyAlpha(m_premultiplyAlpha); - } - - RGBA32Buffer* buffer = &m_frameBufferCache.first(); - if (buffer->status() != RGBA32Buffer::FrameComplete) - decode(false); - return buffer; -} - -bool BMPImageDecoder::setFailed() -{ - m_reader.clear(); - return ImageDecoder::setFailed(); -} - -void BMPImageDecoder::decode(bool onlySize) -{ - if (failed()) - return; - - // If we couldn't decode the image but we've received all the data, decoding - // has failed. - if (!decodeHelper(onlySize) && isAllDataReceived()) - setFailed(); - // If we're done decoding the image, we don't need the BMPImageReader - // anymore. (If we failed, |m_reader| has already been cleared.) - else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == RGBA32Buffer::FrameComplete)) - m_reader.clear(); -} - -bool BMPImageDecoder::decodeHelper(bool onlySize) -{ - size_t imgDataOffset = 0; - if ((m_decodedOffset < sizeOfFileHeader) && !processFileHeader(&imgDataOffset)) - return false; - - if (!m_reader) { - m_reader.set(new BMPImageReader(this, m_decodedOffset, imgDataOffset, false)); - m_reader->setData(m_data.get()); - } - - if (!m_frameBufferCache.isEmpty()) - m_reader->setBuffer(&m_frameBufferCache.first()); - - return m_reader->decodeBMP(onlySize); -} - -bool BMPImageDecoder::processFileHeader(size_t* imgDataOffset) -{ - ASSERT(imgDataOffset); - - // Read file header. - ASSERT(!m_decodedOffset); - if (m_data->size() < sizeOfFileHeader) - return false; - const uint16_t fileType = (m_data->data()[0] << 8) | static_cast<uint8_t>(m_data->data()[1]); - *imgDataOffset = readUint32(10); - m_decodedOffset = sizeOfFileHeader; - - // See if this is a bitmap filetype we understand. - enum { - BMAP = 0x424D, // "BM" - // The following additional OS/2 2.x header values (see - // http://www.fileformat.info/format/os2bmp/egff.htm ) aren't widely - // decoded, and are unlikely to be in much use. - /* - ICON = 0x4943, // "IC" - POINTER = 0x5054, // "PT" - COLORICON = 0x4349, // "CI" - COLORPOINTER = 0x4350, // "CP" - BITMAPARRAY = 0x4241, // "BA" - */ - }; - return (fileType == BMAP) || setFailed(); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h deleted file mode 100644 index 5f4ed82..0000000 --- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h +++ /dev/null @@ -1,85 +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. - */ - -#ifndef BMPImageDecoder_h -#define BMPImageDecoder_h - -#include "BMPImageReader.h" -#include <wtf/OwnPtr.h> - -namespace WebCore { - - // This class decodes the BMP image format. - class BMPImageDecoder : public ImageDecoder { - public: - BMPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - - // ImageDecoder - virtual String filenameExtension() const { return "bmp"; } - virtual void setData(SharedBuffer*, bool allDataReceived); - virtual bool isSizeAvailable(); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid - // accessing deleted memory, especially when calling this from inside - // BMPImageReader! - virtual bool setFailed(); - - private: - inline uint32_t readUint32(int offset) const - { - return BMPImageReader::readUint32(m_data.get(), m_decodedOffset + offset); - } - - // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. If decoding fails but there is no more - // data coming, sets the "decode failure" flag. - void decode(bool onlySize); - - // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. Returns whether decoding succeeded. - bool decodeHelper(bool onlySize); - - // Processes the file header at the beginning of the data. Sets - // |*imgDataOffset| based on the header contents. Returns true if the - // file header could be decoded. - bool processFileHeader(size_t* imgDataOffset); - - // An index into |m_data| representing how much we've already decoded. - // Note that this only tracks data _this_ class decodes; once the - // BMPImageReader takes over this will not be updated further. - size_t m_decodedOffset; - - // The reader used to do most of the BMP decoding. - OwnPtr<BMPImageReader> m_reader; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp b/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp deleted file mode 100644 index 93bedf3..0000000 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.cpp +++ /dev/null @@ -1,737 +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 "BMPImageReader.h" - -namespace WebCore { - -BMPImageReader::BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask) - : m_parent(parent) - , m_buffer(0) - , m_decodedOffset(decodedAndHeaderOffset) - , m_headerOffset(decodedAndHeaderOffset) - , m_imgDataOffset(imgDataOffset) - , m_isOS21x(false) - , m_isOS22x(false) - , m_isTopDown(false) - , m_needToProcessBitmasks(false) - , m_needToProcessColorTable(false) - , m_tableSizeInBytes(0) - , m_seenNonZeroAlphaPixel(false) - , m_seenZeroAlphaPixel(false) - , m_andMaskState(usesAndMask ? NotYetDecoded : None) -{ - // Clue-in decodeBMP() that we need to detect the correct info header size. - memset(&m_infoHeader, 0, sizeof(m_infoHeader)); -} - -bool BMPImageReader::decodeBMP(bool onlySize) -{ - // Calculate size of info header. - if (!m_infoHeader.biSize && !readInfoHeaderSize()) - return false; - - // Read and process info header. - if ((m_decodedOffset < (m_headerOffset + m_infoHeader.biSize)) && !processInfoHeader()) - return false; - - // processInfoHeader() set the size, so if that's all we needed, we're done. - if (onlySize) - return true; - - // Read and process the bitmasks, if needed. - if (m_needToProcessBitmasks && !processBitmasks()) - return false; - - // Read and process the color table, if needed. - if (m_needToProcessColorTable && !processColorTable()) - return false; - - // Initialize the framebuffer if needed. - ASSERT(m_buffer); // Parent should set this before asking us to decode! - if (m_buffer->status() == RGBA32Buffer::FrameEmpty) { - if (!m_buffer->setSize(m_parent->size().width(), m_parent->size().height())) - return m_parent->setFailed(); // Unable to allocate. - m_buffer->setStatus(RGBA32Buffer::FramePartial); - // setSize() calls eraseARGB(), which resets the alpha flag, so we force - // it back to false here. We'll set it true below in all cases where - // these 0s could actually show through. - m_buffer->setHasAlpha(false); - - // For BMPs, the frame always fills the entire image. - m_buffer->setRect(IntRect(IntPoint(), m_parent->size())); - - if (!m_isTopDown) - m_coord.setY(m_parent->size().height() - 1); - } - - // Decode the data. - if ((m_andMaskState != Decoding) && !pastEndOfImage(0)) { - if ((m_infoHeader.biCompression != RLE4) && (m_infoHeader.biCompression != RLE8) && (m_infoHeader.biCompression != RLE24)) { - const ProcessingResult result = processNonRLEData(false, 0); - if (result != Success) - return (result == Failure) ? m_parent->setFailed() : false; - } else if (!processRLEData()) - return false; - } - - // If the image has an AND mask and there was no alpha data, process the - // mask. - if ((m_andMaskState == NotYetDecoded) && !m_buffer->hasAlpha()) { - // Reset decoding coordinates to start of image. - m_coord.setX(0); - m_coord.setY(m_isTopDown ? 0 : (m_parent->size().height() - 1)); - - // The AND mask is stored as 1-bit data. - m_infoHeader.biBitCount = 1; - - m_andMaskState = Decoding; - } - if (m_andMaskState == Decoding) { - const ProcessingResult result = processNonRLEData(false, 0); - if (result != Success) - return (result == Failure) ? m_parent->setFailed() : false; - } - - // Done! - m_buffer->setStatus(RGBA32Buffer::FrameComplete); - return true; -} - -bool BMPImageReader::readInfoHeaderSize() -{ - // Get size of info header. - ASSERT(m_decodedOffset == m_headerOffset); - if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < 4)) - return false; - m_infoHeader.biSize = readUint32(0); - // Don't increment m_decodedOffset here, it just makes the code in - // processInfoHeader() more confusing. - - // Don't allow the header to overflow (which would be harmless here, but - // problematic or at least confusing in other places), or to overrun the - // image data. - if (((m_headerOffset + m_infoHeader.biSize) < m_headerOffset) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize)))) - return m_parent->setFailed(); - - // See if this is a header size we understand: - // OS/2 1.x: 12 - if (m_infoHeader.biSize == 12) - m_isOS21x = true; - // Windows V3: 40 - else if ((m_infoHeader.biSize == 40) || isWindowsV4Plus()) - ; - // OS/2 2.x: any multiple of 4 between 16 and 64, inclusive, or 42 or 46 - else if ((m_infoHeader.biSize >= 16) && (m_infoHeader.biSize <= 64) && (!(m_infoHeader.biSize & 3) || (m_infoHeader.biSize == 42) || (m_infoHeader.biSize == 46))) - m_isOS22x = true; - else - return m_parent->setFailed(); - - return true; -} - -bool BMPImageReader::processInfoHeader() -{ - // Read info header. - ASSERT(m_decodedOffset == m_headerOffset); - if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_infoHeader.biSize) || !readInfoHeader()) - return false; - m_decodedOffset += m_infoHeader.biSize; - - // Sanity-check header values. - if (!isInfoHeaderValid()) - return m_parent->setFailed(); - - // Set our size. - if (!m_parent->setSize(m_infoHeader.biWidth, m_infoHeader.biHeight)) - return false; - - // For paletted images, bitmaps can set biClrUsed to 0 to mean "all - // colors", so set it to the maximum number of colors for this bit depth. - // Also do this for bitmaps that put too large a value here. - if (m_infoHeader.biBitCount < 16) { - const uint32_t maxColors = static_cast<uint32_t>(1) << m_infoHeader.biBitCount; - if (!m_infoHeader.biClrUsed || (m_infoHeader.biClrUsed > maxColors)) - m_infoHeader.biClrUsed = maxColors; - } - - // For any bitmaps that set their BitCount to the wrong value, reset the - // counts now that we've calculated the number of necessary colors, since - // other code relies on this value being correct. - if (m_infoHeader.biCompression == RLE8) - m_infoHeader.biBitCount = 8; - else if (m_infoHeader.biCompression == RLE4) - m_infoHeader.biBitCount = 4; - - // Tell caller what still needs to be processed. - if (m_infoHeader.biBitCount >= 16) - m_needToProcessBitmasks = true; - else if (m_infoHeader.biBitCount) - m_needToProcessColorTable = true; - - return true; -} - -bool BMPImageReader::readInfoHeader() -{ - // Pre-initialize some fields that not all headers set. - m_infoHeader.biCompression = RGB; - m_infoHeader.biClrUsed = 0; - - if (m_isOS21x) { - m_infoHeader.biWidth = readUint16(4); - m_infoHeader.biHeight = readUint16(6); - ASSERT(m_andMaskState == None); // ICO is a Windows format, not OS/2! - m_infoHeader.biBitCount = readUint16(10); - return true; - } - - m_infoHeader.biWidth = readUint32(4); - m_infoHeader.biHeight = readUint32(8); - if (m_andMaskState != None) - m_infoHeader.biHeight /= 2; - m_infoHeader.biBitCount = readUint16(14); - - // Read compression type, if present. - if (m_infoHeader.biSize >= 20) { - uint32_t biCompression = readUint32(16); - - // Detect OS/2 2.x-specific compression types. - if ((biCompression == 3) && (m_infoHeader.biBitCount == 1)) { - m_infoHeader.biCompression = HUFFMAN1D; - m_isOS22x = true; - } else if ((biCompression == 4) && (m_infoHeader.biBitCount == 24)) { - m_infoHeader.biCompression = RLE24; - m_isOS22x = true; - } else if (biCompression > 5) - return m_parent->setFailed(); // Some type we don't understand. - else - m_infoHeader.biCompression = static_cast<CompressionType>(biCompression); - } - - // Read colors used, if present. - if (m_infoHeader.biSize >= 36) - m_infoHeader.biClrUsed = readUint32(32); - - // Windows V4+ can safely read the four bitmasks from 40-56 bytes in, so do - // that here. If the bit depth is less than 16, these values will be - // ignored by the image data decoders. If the bit depth is at least 16 but - // the compression format isn't BITFIELDS, these values will be ignored and - // overwritten* in processBitmasks(). - // NOTE: We allow alpha here. Microsoft doesn't really document this well, - // but some BMPs appear to use it. - // - // For non-Windows V4+, m_bitMasks[] et. al will be initialized later - // during processBitmasks(). - // - // *Except the alpha channel. Bizarrely, some RGB bitmaps expect decoders - // to pay attention to the alpha mask here, so there's a special case in - // processBitmasks() that doesn't always overwrite that value. - if (isWindowsV4Plus()) { - m_bitMasks[0] = readUint32(40); - m_bitMasks[1] = readUint32(44); - m_bitMasks[2] = readUint32(48); - m_bitMasks[3] = readUint32(52); - } - - // Detect top-down BMPs. - if (m_infoHeader.biHeight < 0) { - m_isTopDown = true; - m_infoHeader.biHeight = -m_infoHeader.biHeight; - } - - return true; -} - -bool BMPImageReader::isInfoHeaderValid() const -{ - // Non-positive widths/heights are invalid. (We've already flipped the - // sign of the height for top-down bitmaps.) - if ((m_infoHeader.biWidth <= 0) || !m_infoHeader.biHeight) - return false; - - // Only Windows V3+ has top-down bitmaps. - if (m_isTopDown && (m_isOS21x || m_isOS22x)) - return false; - - // Only bit depths of 1, 4, 8, or 24 are universally supported. - if ((m_infoHeader.biBitCount != 1) && (m_infoHeader.biBitCount != 4) && (m_infoHeader.biBitCount != 8) && (m_infoHeader.biBitCount != 24)) { - // Windows V3+ additionally supports bit depths of 0 (for embedded - // JPEG/PNG images), 16, and 32. - if (m_isOS21x || m_isOS22x || (m_infoHeader.biBitCount && (m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32))) - return false; - } - - // Each compression type is only valid with certain bit depths (except RGB, - // which can be used with any bit depth). Also, some formats do not - // some compression types. - switch (m_infoHeader.biCompression) { - case RGB: - if (!m_infoHeader.biBitCount) - return false; - break; - - case RLE8: - // Supposedly there are undocumented formats like "BitCount = 1, - // Compression = RLE4" (which means "4 bit, but with a 2-color table"), - // so also allow the paletted RLE compression types to have too low a - // bit count; we'll correct this later. - if (!m_infoHeader.biBitCount || (m_infoHeader.biBitCount > 8)) - return false; - break; - - case RLE4: - // See comments in RLE8. - if (!m_infoHeader.biBitCount || (m_infoHeader.biBitCount > 4)) - return false; - break; - - case BITFIELDS: - // Only valid for Windows V3+. - if (m_isOS21x || m_isOS22x || ((m_infoHeader.biBitCount != 16) && (m_infoHeader.biBitCount != 32))) - return false; - break; - - case JPEG: - case PNG: - // Only valid for Windows V3+. - if (m_isOS21x || m_isOS22x || m_infoHeader.biBitCount) - return false; - break; - - case HUFFMAN1D: - // Only valid for OS/2 2.x. - if (!m_isOS22x || (m_infoHeader.biBitCount != 1)) - return false; - break; - - case RLE24: - // Only valid for OS/2 2.x. - if (!m_isOS22x || (m_infoHeader.biBitCount != 24)) - return false; - break; - - default: - // Some type we don't understand. This should have been caught in - // readInfoHeader(). - ASSERT_NOT_REACHED(); - return false; - } - - // Top-down bitmaps cannot be compressed; they must be RGB or BITFIELDS. - if (m_isTopDown && (m_infoHeader.biCompression != RGB) && (m_infoHeader.biCompression != BITFIELDS)) - return false; - - // Reject the following valid bitmap types that we don't currently bother - // decoding. Few other people decode these either, they're unlikely to be - // in much use. - // TODO(pkasting): Consider supporting these someday. - // * Bitmaps larger than 2^16 pixels in either dimension (Windows - // probably doesn't draw these well anyway, and the decoded data would - // take a lot of memory). - if ((m_infoHeader.biWidth >= (1 << 16)) || (m_infoHeader.biHeight >= (1 << 16))) - return false; - // * Windows V3+ JPEG-in-BMP and PNG-in-BMP bitmaps (supposedly not found - // in the wild, only used to send data to printers?). - if ((m_infoHeader.biCompression == JPEG) || (m_infoHeader.biCompression == PNG)) - return false; - // * OS/2 2.x Huffman-encoded monochrome bitmaps (see - // http://www.fileformat.info/mirror/egff/ch09_05.htm , re: "G31D" - // algorithm). - if (m_infoHeader.biCompression == HUFFMAN1D) - return false; - - return true; -} - -bool BMPImageReader::processBitmasks() -{ - // Create m_bitMasks[] values. - if (m_infoHeader.biCompression != BITFIELDS) { - // The format doesn't actually use bitmasks. To simplify the decode - // logic later, create bitmasks for the RGB data. For Windows V4+, - // this overwrites the masks we read from the header, which are - // supposed to be ignored in non-BITFIELDS cases. - // 16 bits: MSB <- xRRRRRGG GGGBBBBB -> LSB - // 24/32 bits: MSB <- [AAAAAAAA] RRRRRRRR GGGGGGGG BBBBBBBB -> LSB - const int numBits = (m_infoHeader.biBitCount == 16) ? 5 : 8; - for (int i = 0; i <= 2; ++i) - m_bitMasks[i] = ((static_cast<uint32_t>(1) << (numBits * (3 - i))) - 1) ^ ((static_cast<uint32_t>(1) << (numBits * (2 - i))) - 1); - - // For Windows V4+ 32-bit RGB, don't overwrite the alpha mask from the - // header (see note in readInfoHeader()). - if (m_infoHeader.biBitCount < 32) - m_bitMasks[3] = 0; - else if (!isWindowsV4Plus()) - m_bitMasks[3] = static_cast<uint32_t>(0xff000000); - } else if (!isWindowsV4Plus()) { - // For Windows V4+ BITFIELDS mode bitmaps, this was already done when - // we read the info header. - - // Fail if we don't have enough file space for the bitmasks. - static const size_t SIZEOF_BITMASKS = 12; - if (((m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + SIZEOF_BITMASKS)))) - return m_parent->setFailed(); - - // Read bitmasks. - if ((m_data->size() - m_decodedOffset) < SIZEOF_BITMASKS) - return false; - m_bitMasks[0] = readUint32(0); - m_bitMasks[1] = readUint32(4); - m_bitMasks[2] = readUint32(8); - // No alpha in anything other than Windows V4+. - m_bitMasks[3] = 0; - - m_decodedOffset += SIZEOF_BITMASKS; - } - - // We've now decoded all the non-image data we care about. Skip anything - // else before the actual raster data. - if (m_imgDataOffset) - m_decodedOffset = m_imgDataOffset; - m_needToProcessBitmasks = false; - - // Check masks and set shift values. - for (int i = 0; i < 4; ++i) { - // Trim the mask to the allowed bit depth. Some Windows V4+ BMPs - // specify a bogus alpha channel in bits that don't exist in the pixel - // data (for example, bits 25-31 in a 24-bit RGB format). - if (m_infoHeader.biBitCount < 32) - m_bitMasks[i] &= ((static_cast<uint32_t>(1) << m_infoHeader.biBitCount) - 1); - - // For empty masks (common on the alpha channel, especially after the - // trimming above), quickly clear the shifts and continue, to avoid an - // infinite loop in the counting code below. - uint32_t tempMask = m_bitMasks[i]; - if (!tempMask) { - m_bitShiftsRight[i] = m_bitShiftsLeft[i] = 0; - continue; - } - - // Make sure bitmask does not overlap any other bitmasks. - for (int j = 0; j < i; ++j) { - if (tempMask & m_bitMasks[j]) - return m_parent->setFailed(); - } - - // Count offset into pixel data. - for (m_bitShiftsRight[i] = 0; !(tempMask & 1); tempMask >>= 1) - ++m_bitShiftsRight[i]; - - // Count size of mask. - for (m_bitShiftsLeft[i] = 8; tempMask & 1; tempMask >>= 1) - --m_bitShiftsLeft[i]; - - // Make sure bitmask is contiguous. - if (tempMask) - return m_parent->setFailed(); - - // Since RGBABuffer tops out at 8 bits per channel, adjust the shift - // amounts to use the most significant 8 bits of the channel. - if (m_bitShiftsLeft[i] < 0) { - m_bitShiftsRight[i] -= m_bitShiftsLeft[i]; - m_bitShiftsLeft[i] = 0; - } - } - - return true; -} - -bool BMPImageReader::processColorTable() -{ - m_tableSizeInBytes = m_infoHeader.biClrUsed * (m_isOS21x ? 3 : 4); - - // Fail if we don't have enough file space for the color table. - if (((m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes) < (m_headerOffset + m_infoHeader.biSize)) || (m_imgDataOffset && (m_imgDataOffset < (m_headerOffset + m_infoHeader.biSize + m_tableSizeInBytes)))) - return m_parent->setFailed(); - - // Read color table. - if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < m_tableSizeInBytes)) - return false; - m_colorTable.resize(m_infoHeader.biClrUsed); - for (size_t i = 0; i < m_infoHeader.biClrUsed; ++i) { - m_colorTable[i].rgbBlue = m_data->data()[m_decodedOffset++]; - m_colorTable[i].rgbGreen = m_data->data()[m_decodedOffset++]; - m_colorTable[i].rgbRed = m_data->data()[m_decodedOffset++]; - // Skip padding byte (not present on OS/2 1.x). - if (!m_isOS21x) - ++m_decodedOffset; - } - - // We've now decoded all the non-image data we care about. Skip anything - // else before the actual raster data. - if (m_imgDataOffset) - m_decodedOffset = m_imgDataOffset; - m_needToProcessColorTable = false; - - return true; -} - -bool BMPImageReader::processRLEData() -{ - if (m_decodedOffset > m_data->size()) - return false; - - // RLE decoding is poorly specified. Two main problems: - // (1) Are EOL markers necessary? What happens when we have too many - // pixels for one row? - // http://www.fileformat.info/format/bmp/egff.htm says extra pixels - // should wrap to the next line. Real BMPs I've encountered seem to - // instead expect extra pixels to be ignored until the EOL marker is - // seen, although this has only happened in a few cases and I suspect - // those BMPs may be invalid. So we only change lines on EOL (or Delta - // with dy > 0), and fail in most cases when pixels extend past the end - // of the line. - // (2) When Delta, EOL, or EOF are seen, what happens to the "skipped" - // pixels? - // http://www.daubnet.com/formats/BMP.html says these should be filled - // with color 0. However, the "do nothing" and "don't care" comments - // of other references suggest leaving these alone, i.e. letting them - // be transparent to the background behind the image. This seems to - // match how MSPAINT treats BMPs, so we do that. Note that when we - // actually skip pixels for a case like this, we need to note on the - // framebuffer that we have alpha. - - // Impossible to decode row-at-a-time, so just do things as a stream of - // bytes. - while (true) { - // Every entry takes at least two bytes; bail if there isn't enough - // data. - if ((m_data->size() - m_decodedOffset) < 2) - return false; - - // For every entry except EOF, we'd better not have reached the end of - // the image. - const uint8_t count = m_data->data()[m_decodedOffset]; - const uint8_t code = m_data->data()[m_decodedOffset + 1]; - if ((count || (code != 1)) && pastEndOfImage(0)) - return m_parent->setFailed(); - - // Decode. - if (!count) { - switch (code) { - case 0: // Magic token: EOL - // Skip any remaining pixels in this row. - if (m_coord.x() < m_parent->size().width()) - m_buffer->setHasAlpha(true); - moveBufferToNextRow(); - - m_decodedOffset += 2; - break; - - case 1: // Magic token: EOF - // Skip any remaining pixels in the image. - if ((m_coord.x() < m_parent->size().width()) || (m_isTopDown ? (m_coord.y() < (m_parent->size().height() - 1)) : (m_coord.y() > 0))) - m_buffer->setHasAlpha(true); - return true; - - case 2: { // Magic token: Delta - // The next two bytes specify dx and dy. Bail if there isn't - // enough data. - if ((m_data->size() - m_decodedOffset) < 4) - return false; - - // Fail if this takes us past the end of the desired row or - // past the end of the image. - const uint8_t dx = m_data->data()[m_decodedOffset + 2]; - const uint8_t dy = m_data->data()[m_decodedOffset + 3]; - if (dx || dy) - m_buffer->setHasAlpha(true); - if (((m_coord.x() + dx) > m_parent->size().width()) || pastEndOfImage(dy)) - return m_parent->setFailed(); - - // Skip intervening pixels. - m_coord.move(dx, m_isTopDown ? dy : -dy); - - m_decodedOffset += 4; - break; - } - - default: { // Absolute mode - // |code| pixels specified as in BI_RGB, zero-padded at the end - // to a multiple of 16 bits. - // Because processNonRLEData() expects m_decodedOffset to - // point to the beginning of the pixel data, bump it past - // the escape bytes and then reset if decoding failed. - m_decodedOffset += 2; - const ProcessingResult result = processNonRLEData(true, code); - if (result == Failure) - return m_parent->setFailed(); - if (result == InsufficientData) { - m_decodedOffset -= 2; - return false; - } - break; - } - } - } else { // Encoded mode - // The following color data is repeated for |count| total pixels. - // Strangely, some BMPs seem to specify excessively large counts - // here; ignore pixels past the end of the row. - const int endX = std::min(m_coord.x() + count, m_parent->size().width()); - - if (m_infoHeader.biCompression == RLE24) { - // Bail if there isn't enough data. - if ((m_data->size() - m_decodedOffset) < 4) - return false; - - // One BGR triple that we copy |count| times. - fillRGBA(endX, m_data->data()[m_decodedOffset + 3], m_data->data()[m_decodedOffset + 2], code, 0xff); - m_decodedOffset += 4; - } else { - // RLE8 has one color index that gets repeated; RLE4 has two - // color indexes in the upper and lower 4 bits of the byte, - // which are alternated. - size_t colorIndexes[2] = {code, code}; - if (m_infoHeader.biCompression == RLE4) { - colorIndexes[0] = (colorIndexes[0] >> 4) & 0xf; - colorIndexes[1] &= 0xf; - } - if ((colorIndexes[0] >= m_infoHeader.biClrUsed) || (colorIndexes[1] >= m_infoHeader.biClrUsed)) - return m_parent->setFailed(); - for (int which = 0; m_coord.x() < endX; ) { - setI(colorIndexes[which]); - which = !which; - } - - m_decodedOffset += 2; - } - } - } -} - -BMPImageReader::ProcessingResult BMPImageReader::processNonRLEData(bool inRLE, int numPixels) -{ - if (m_decodedOffset > m_data->size()) - return InsufficientData; - - if (!inRLE) - numPixels = m_parent->size().width(); - - // Fail if we're being asked to decode more pixels than remain in the row. - const int endX = m_coord.x() + numPixels; - if (endX > m_parent->size().width()) - return Failure; - - // Determine how many bytes of data the requested number of pixels - // requires. - const size_t pixelsPerByte = 8 / m_infoHeader.biBitCount; - const size_t bytesPerPixel = m_infoHeader.biBitCount / 8; - const size_t unpaddedNumBytes = (m_infoHeader.biBitCount < 16) ? ((numPixels + pixelsPerByte - 1) / pixelsPerByte) : (numPixels * bytesPerPixel); - // RLE runs are zero-padded at the end to a multiple of 16 bits. Non-RLE - // data is in rows and is zero-padded to a multiple of 32 bits. - const size_t alignBits = inRLE ? 1 : 3; - const size_t paddedNumBytes = (unpaddedNumBytes + alignBits) & ~alignBits; - - // Decode as many rows as we can. (For RLE, where we only want to decode - // one row, we've already checked that this condition is true.) - while (!pastEndOfImage(0)) { - // Bail if we don't have enough data for the desired number of pixels. - if ((m_data->size() - m_decodedOffset) < paddedNumBytes) - return InsufficientData; - - if (m_infoHeader.biBitCount < 16) { - // Paletted data. Pixels are stored little-endian within bytes. - // Decode pixels one byte at a time, left to right (so, starting at - // the most significant bits in the byte). - const uint8_t mask = (1 << m_infoHeader.biBitCount) - 1; - for (size_t byte = 0; byte < unpaddedNumBytes; ++byte) { - uint8_t pixelData = m_data->data()[m_decodedOffset + byte]; - for (size_t pixel = 0; (pixel < pixelsPerByte) && (m_coord.x() < endX); ++pixel) { - const size_t colorIndex = (pixelData >> (8 - m_infoHeader.biBitCount)) & mask; - if (m_andMaskState == Decoding) { - // There's no way to accurately represent an AND + XOR - // operation as an RGBA image, so where the AND values - // are 1, we simply set the framebuffer pixels to fully - // transparent, on the assumption that most ICOs on the - // web will not be doing a lot of inverting. - if (colorIndex) { - setRGBA(0, 0, 0, 0); - m_buffer->setHasAlpha(true); - } else - m_coord.move(1, 0); - } else { - if (colorIndex >= m_infoHeader.biClrUsed) - return Failure; - setI(colorIndex); - } - pixelData <<= m_infoHeader.biBitCount; - } - } - } else { - // RGB data. Decode pixels one at a time, left to right. - while (m_coord.x() < endX) { - const uint32_t pixel = readCurrentPixel(bytesPerPixel); - - // Some BMPs specify an alpha channel but don't actually use it - // (it contains all 0s). To avoid displaying these images as - // fully-transparent, decode as if images are fully opaque - // until we actually see a non-zero alpha value; at that point, - // reset any previously-decoded pixels to fully transparent and - // continue decoding based on the real alpha channel values. - // As an optimization, avoid setting "hasAlpha" to true for - // images where all alpha values are 255; opaque images are - // faster to draw. - int alpha = getAlpha(pixel); - if (!m_seenNonZeroAlphaPixel && !alpha) { - m_seenZeroAlphaPixel = true; - alpha = 255; - } else { - m_seenNonZeroAlphaPixel = true; - if (m_seenZeroAlphaPixel) { - m_buffer->zeroFill(); - m_seenZeroAlphaPixel = false; - } else if (alpha != 255) - m_buffer->setHasAlpha(true); - } - - setRGBA(getComponent(pixel, 0), getComponent(pixel, 1), - getComponent(pixel, 2), alpha); - } - } - - // Success, keep going. - m_decodedOffset += paddedNumBytes; - if (inRLE) - return Success; - moveBufferToNextRow(); - } - - // Finished decoding whole image. - return Success; -} - -void BMPImageReader::moveBufferToNextRow() -{ - m_coord.move(-m_coord.x(), m_isTopDown ? 1 : -1); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/bmp/BMPImageReader.h b/WebCore/platform/image-decoders/bmp/BMPImageReader.h deleted file mode 100644 index 0a6dc84..0000000 --- a/WebCore/platform/image-decoders/bmp/BMPImageReader.h +++ /dev/null @@ -1,354 +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. - */ - -#ifndef BMPImageReader_h -#define BMPImageReader_h - -#include <stdint.h> -#include "ImageDecoder.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 { - 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 RGBA32Buffer that we'll initialize and - // fill with decoded data. - BMPImageReader(ImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask); - - void setBuffer(RGBA32Buffer* 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) - { - setRGBA(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff); - } - - // Like setI(), but with the individual component values specified. - inline void setRGBA(unsigned red, - unsigned green, - unsigned blue, - unsigned alpha) - { - m_buffer->setRGBA(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) - { - while (m_coord.x() < endCoord) - setRGBA(red, green, blue, alpha); - } - - // 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. - ImageDecoder* m_parent; - - // The destination for the pixel data. - RGBA32Buffer* 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 - -#endif diff --git a/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp b/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp deleted file mode 100644 index d741882..0000000 --- a/WebCore/platform/image-decoders/cairo/ImageDecoderCairo.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" - -#include <cairo.h> - -namespace WebCore { - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ - return cairo_image_surface_create_for_data( - reinterpret_cast<unsigned char*>(const_cast<PixelData*>( - m_bytes)), CAIRO_FORMAT_ARGB32, width(), height(), - width() * sizeof(PixelData)); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp b/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp deleted file mode 100644 index 3974f0e..0000000 --- a/WebCore/platform/image-decoders/cg/ImageDecoderCG.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2010 Google, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" - -#include <CoreGraphics/CGColorSpace.h> -#include <CoreGraphics/CGImage.h> - -namespace WebCore { - -static RGBA32Buffer::PixelData* getPtrAsPixelData(CFMutableDataRef data) -{ - return data ? reinterpret_cast<RGBA32Buffer::PixelData*>(CFDataGetMutableBytePtr(data)) : 0; -} - -void RGBA32Buffer::copyReferenceToBitmapData(const RGBA32Buffer& other) -{ - ASSERT(this != &other); - m_backingStore = other.m_backingStore; - m_bytes = getPtrAsPixelData(m_backingStore.get()); - // FIXME: The rest of this function seems redundant with RGBA32Buffer::copyBitmapData. - m_size = other.m_size; - setHasAlpha(other.m_hasAlpha); -} - -bool RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) -{ - if (this == &other) - return true; - - m_backingStore.adoptCF(CFDataCreateMutableCopy(kCFAllocatorDefault, 0, other.m_backingStore.get())); - m_bytes = getPtrAsPixelData(m_backingStore.get()); - m_size = other.m_size; - setHasAlpha(other.m_hasAlpha); - return true; -} - -bool RGBA32Buffer::setSize(int newWidth, int newHeight) -{ - ASSERT(!m_backingStore); - size_t backingStoreSize = newWidth * newHeight * sizeof(PixelData); - CFMutableDataRef backingStoreRef = CFDataCreateMutable(kCFAllocatorDefault, backingStoreSize); - if (!backingStoreRef) - return false; - m_backingStore.adoptCF(backingStoreRef); - CFDataSetLength(backingStoreRef, backingStoreSize); - m_bytes = reinterpret_cast<PixelData*>(CFDataGetMutableBytePtr(m_backingStore.get())); - m_size = IntSize(newWidth, newHeight); - - zeroFill(); - return true; -} - -static CGColorSpaceRef createColorSpace(const ColorProfile& colorProfile) -{ - if (colorProfile.isEmpty()) - return CGColorSpaceCreateDeviceRGB(); - - RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(colorProfile.data()), colorProfile.size())); -#if !defined(TARGETING_TIGER) && !defined(TARGETING_LEOPARD) - return CGColorSpaceCreateWithICCProfile(data.get()); -#else - RetainPtr<CGColorSpaceRef> deviceColorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB()); - RetainPtr<CGDataProviderRef> profileDataProvider(AdoptCF, CGDataProviderCreateWithCFData(data.get())); - CGFloat ranges[] = {0.0, 255.0, 0.0, 255.0, 0.0, 255.0}; - return CGColorSpaceCreateICCBased(3, ranges, profileDataProvider.get(), deviceColorSpace.get()); -#endif -} - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ - RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, createColorSpace(m_colorProfile)); - RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithCFData(m_backingStore.get())); - - CGImageAlphaInfo alphaInfo = m_premultiplyAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaFirst; - - return CGImageCreate(width(), height(), 8, 32, width() * sizeof(PixelData), colorSpace.get(), - alphaInfo | kCGBitmapByteOrder32Host, dataProvider.get(), 0, /*shouldInterpolate=*/true, kCGRenderingIntentDefault); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp deleted file mode 100644 index e92f264..0000000 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "GIFImageDecoder.h" -#include "GIFImageReader.h" - -namespace WebCore { - -GIFImageDecoder::GIFImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) - , m_alreadyScannedThisDataForFrameCount(true) - , m_repetitionCount(cAnimationLoopOnce) - , m_readOffset(0) -{ -} - -GIFImageDecoder::~GIFImageDecoder() -{ -} - -void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - if (failed()) - return; - - ImageDecoder::setData(data, allDataReceived); - - // We need to rescan the frame count, as the new data may have changed it. - m_alreadyScannedThisDataForFrameCount = false; -} - -bool GIFImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(0, GIFSizeQuery); - - return ImageDecoder::isSizeAvailable(); -} - -bool GIFImageDecoder::setSize(int width, int height) -{ - if (ImageDecoder::isSizeAvailable() && size().width() == width && size().height() == height) - return true; - - if (!ImageDecoder::setSize(width, height)) - return false; - - prepareScaleDataIfNecessary(); - return true; -} - -size_t GIFImageDecoder::frameCount() -{ - if (!m_alreadyScannedThisDataForFrameCount) { - // FIXME: Scanning all the data has O(n^2) behavior if the data were to - // come in really slowly. Might be interesting to try to clone our - // existing read session to preserve state, but for now we just crawl - // all the data. Note that this is no worse than what ImageIO does on - // Mac right now (it also crawls all the data again). - GIFImageReader reader(0); - reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1)); - m_alreadyScannedThisDataForFrameCount = true; - m_frameBufferCache.resize(reader.images_count); - for (int i = 0; i < reader.images_count; ++i) - m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha); - } - - return m_frameBufferCache.size(); -} - -int GIFImageDecoder::repetitionCount() const -{ - // This value can arrive at any point in the image data stream. Most GIFs - // in the wild declare it near the beginning of the file, so it usually is - // set by the time we've decoded the size, but (depending on the GIF and the - // packets sent back by the webserver) not always. If the reader hasn't - // seen a loop count yet, it will return cLoopCountNotSeen, in which case we - // should default to looping once (the initial value for - // |m_repetitionCount|). - // - // There are two additional wrinkles here. First, ImageSource::clear() may - // destroy the reader, making the result from the reader _less_ - // authoritative on future calls if the recreated reader hasn't seen the - // loop count. We don't need to special-case this because in this case the - // new reader will once again return cLoopCountNotSeen, and we won't - // overwrite the cached correct value. - // - // Second, a GIF might never set a loop count at all, in which case we - // should continue to treat it as a "loop once" animation. We don't need - // special code here either, because in this case we'll never change - // |m_repetitionCount| from its default value. - if (m_reader && (m_reader->loop_count != cLoopCountNotSeen)) - m_repetitionCount = m_reader->loop_count; - return m_repetitionCount; -} - -RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index >= frameCount()) - return 0; - - RGBA32Buffer& frame = m_frameBufferCache[index]; - if (frame.status() != RGBA32Buffer::FrameComplete) - decode(index + 1, GIFFullQuery); - return &frame; -} - -bool GIFImageDecoder::setFailed() -{ - m_reader.clear(); - return ImageDecoder::setFailed(); -} - -void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame) -{ - // In some cases, like if the decoder was destroyed while animating, we - // can be asked to clear more frames than we currently have. - if (m_frameBufferCache.isEmpty()) - return; // Nothing to do. - - // The "-1" here is tricky. It does not mean that |clearBeforeFrame| is the - // last frame we wish to preserve, but rather that we never want to clear - // the very last frame in the cache: it's empty (so clearing it is - // pointless), it's partial (so we don't want to clear it anyway), or the - // cache could be enlarged with a future setData() call and it could be - // needed to construct the next frame (see comments below). Callers can - // always use ImageSource::clear(true, ...) to completely free the memory in - // this case. - clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1); - const Vector<RGBA32Buffer>::iterator end(m_frameBufferCache.begin() + clearBeforeFrame); - - // We need to preserve frames such that: - // * We don't clear |end| - // * We don't clear the frame we're currently decoding - // * We don't clear any frame from which a future initFrameBuffer() call - // will copy bitmap data - // All other frames can be cleared. Because of the constraints on when - // ImageSource::clear() can be called (see ImageSource.h), we're guaranteed - // not to have non-empty frames after the frame we're currently decoding. - // So, scan backwards from |end| as follows: - // * If the frame is empty, we're still past any frames we care about. - // * If the frame is complete, but is DisposeOverwritePrevious, we'll - // skip over it in future initFrameBuffer() calls. We can clear it - // unless it's |end|, and keep scanning. For any other disposal method, - // stop scanning, as we've found the frame initFrameBuffer() will need - // next. - // * If the frame is partial, we're decoding it, so don't clear it; if it - // has a disposal method other than DisposeOverwritePrevious, stop - // scanning, as we'll only need this frame when decoding the next one. - Vector<RGBA32Buffer>::iterator i(end); - for (; (i != m_frameBufferCache.begin()) && ((i->status() == RGBA32Buffer::FrameEmpty) || (i->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)); --i) { - if ((i->status() == RGBA32Buffer::FrameComplete) && (i != end)) - i->clear(); - } - - // Now |i| holds the last frame we need to preserve; clear prior frames. - for (Vector<RGBA32Buffer>::iterator j(m_frameBufferCache.begin()); j != i; ++j) { - ASSERT(j->status() != RGBA32Buffer::FramePartial); - if (j->status() != RGBA32Buffer::FrameEmpty) - j->clear(); - } -} - -void GIFImageDecoder::decodingHalted(unsigned bytesLeft) -{ - m_readOffset = m_data->size() - bytesLeft; -} - -bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) -{ - const GIFFrameReader* frameReader = m_reader->frame_reader; - // The pixel data and coordinates supplied to us are relative to the frame's - // origin within the entire image size, i.e. - // (frameReader->x_offset, frameReader->y_offset). There is no guarantee - // that (rowEnd - rowBuffer) == (size().width() - frameReader->x_offset), so - // we must ensure we don't run off the end of either the source data or the - // row's X-coordinates. - int xBegin = upperBoundScaledX(frameReader->x_offset); - int yBegin = upperBoundScaledY(frameReader->y_offset + rowNumber); - int xEnd = lowerBoundScaledX(std::min(static_cast<int>(frameReader->x_offset + (rowEnd - rowBuffer)), size().width()) - 1, xBegin + 1) + 1; - int yEnd = lowerBoundScaledY(std::min(static_cast<int>(frameReader->y_offset + rowNumber + repeatCount), size().height()) - 1, yBegin + 1) + 1; - if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) - return true; - - // Get the colormap. - const unsigned char* colorMap; - unsigned colorMapSize; - if (frameReader->is_local_colormap_defined) { - colorMap = frameReader->local_colormap; - colorMapSize = (unsigned)frameReader->local_colormap_size; - } else { - colorMap = m_reader->global_colormap; - colorMapSize = m_reader->global_colormap_size; - } - if (!colorMap) - return true; - - // Initialize the frame if necessary. - RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; - if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) - return false; - - // Write one row's worth of data into the frame. - for (int x = xBegin; x < xEnd; ++x) { - const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frameReader->x_offset); - if ((!frameReader->is_transparent || (sourceValue != frameReader->tpixel)) && (sourceValue < colorMapSize)) { - const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; - buffer.setRGBA(x, yBegin, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); - } else { - m_currentBufferSawAlpha = true; - // We may or may not need to write transparent pixels to the buffer. - // If we're compositing against a previous image, it's wrong, and if - // we're writing atop a cleared, fully transparent buffer, it's - // unnecessary; but if we're decoding an interlaced gif and - // displaying it "Haeberli"-style, we must write these for passes - // beyond the first, or the initial passes will "show through" the - // later ones. - if (writeTransparentPixels) - buffer.setRGBA(x, yBegin, 0, 0, 0, 0); - } - } - - // Tell the frame to copy the row data if need be. - if (repeatCount > 1) - buffer.copyRowNTimes(xBegin, xEnd, yBegin, yEnd); - - return true; -} - -bool GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod) -{ - // Initialize the frame if necessary. Some GIFs insert do-nothing frames, - // in which case we never reach haveDecodedRow() before getting here. - RGBA32Buffer& buffer = m_frameBufferCache[frameIndex]; - if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex)) - return false; // initFrameBuffer() has already called setFailed(). - - buffer.setStatus(RGBA32Buffer::FrameComplete); - buffer.setDuration(frameDuration); - buffer.setDisposalMethod(disposalMethod); - - if (!m_currentBufferSawAlpha) { - // The whole frame was non-transparent, so it's possible that the entire - // resulting buffer was non-transparent, and we can setHasAlpha(false). - if (buffer.rect().contains(IntRect(IntPoint(), scaledSize()))) - buffer.setHasAlpha(false); - else if (frameIndex) { - // Tricky case. This frame does not have alpha only if everywhere - // outside its rect doesn't have alpha. To know whether this is - // true, we check the start state of the frame -- if it doesn't have - // alpha, we're safe. - // - // First skip over prior DisposeOverwritePrevious frames (since they - // don't affect the start state of this frame) the same way we do in - // initFrameBuffer(). - const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; - while (frameIndex && (prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)) - prevBuffer = &m_frameBufferCache[--frameIndex]; - - // Now, if we're at a DisposeNotSpecified or DisposeKeep frame, then - // we can say we have no alpha if that frame had no alpha. But - // since in initFrameBuffer() we already copied that frame's alpha - // state into the current frame's, we need do nothing at all here. - // - // The only remaining case is a DisposeOverwriteBgcolor frame. If - // it had no alpha, and its rect is contained in the current frame's - // rect, we know the current frame has no alpha. - if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor) && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect())) - buffer.setHasAlpha(false); - } - } - - return true; -} - -void GIFImageDecoder::gifComplete() -{ - // Cache the repetition count, which is now as authoritative as it's ever - // going to be. - repetitionCount(); - - m_reader.clear(); -} - -void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query) -{ - if (failed()) - return; - - if (!m_reader) - m_reader.set(new GIFImageReader(this)); - - // If we couldn't decode the image but we've received all the data, decoding - // has failed. - if (!m_reader->read((const unsigned char*)m_data->data() + m_readOffset, m_data->size() - m_readOffset, query, haltAtFrame) && isAllDataReceived()) - setFailed(); -} - -bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex) -{ - // Initialize the frame rect in our buffer. - const GIFFrameReader* frameReader = m_reader->frame_reader; - IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height); - - // Make sure the frameRect doesn't extend outside the buffer. - if (frameRect.right() > size().width()) - frameRect.setWidth(size().width() - frameReader->x_offset); - if (frameRect.bottom() > size().height()) - frameRect.setHeight(size().height() - frameReader->y_offset); - - RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex]; - int left = upperBoundScaledX(frameRect.x()); - int right = lowerBoundScaledX(frameRect.right(), left); - int top = upperBoundScaledY(frameRect.y()); - int bottom = lowerBoundScaledY(frameRect.bottom(), top); - buffer->setRect(IntRect(left, top, right - left, bottom - top)); - - if (!frameIndex) { - // This is the first frame, so we're not relying on any previous data. - if (!buffer->setSize(scaledSize().width(), scaledSize().height())) - return setFailed(); - } else { - // The starting state for this frame depends on the previous frame's - // disposal method. - // - // Frames that use the DisposeOverwritePrevious method are effectively - // no-ops in terms of changing the starting state of a frame compared to - // the starting state of the previous frame, so skip over them. (If the - // first frame specifies this method, it will get treated like - // DisposeOverwriteBgcolor below and reset to a completely empty image.) - const RGBA32Buffer* prevBuffer = &m_frameBufferCache[--frameIndex]; - RGBA32Buffer::FrameDisposalMethod prevMethod = prevBuffer->disposalMethod(); - while (frameIndex && (prevMethod == RGBA32Buffer::DisposeOverwritePrevious)) { - prevBuffer = &m_frameBufferCache[--frameIndex]; - prevMethod = prevBuffer->disposalMethod(); - } - ASSERT(prevBuffer->status() == RGBA32Buffer::FrameComplete); - - if ((prevMethod == RGBA32Buffer::DisposeNotSpecified) || (prevMethod == RGBA32Buffer::DisposeKeep)) { - // Preserve the last frame as the starting state for this frame. - if (!buffer->copyBitmapData(*prevBuffer)) - return setFailed(); - } else { - // We want to clear the previous frame to transparent, without - // affecting pixels in the image outside of the frame. - const IntRect& prevRect = prevBuffer->rect(); - const IntSize& bufferSize = scaledSize(); - if (!frameIndex || prevRect.contains(IntRect(IntPoint(), scaledSize()))) { - // Clearing the first frame, or a frame the size of the whole - // image, results in a completely empty image. - if (!buffer->setSize(bufferSize.width(), bufferSize.height())) - return setFailed(); - } else { - // Copy the whole previous buffer, then clear just its frame. - if (!buffer->copyBitmapData(*prevBuffer)) - return setFailed(); - for (int y = prevRect.y(); y < prevRect.bottom(); ++y) { - for (int x = prevRect.x(); x < prevRect.right(); ++x) - buffer->setRGBA(x, y, 0, 0, 0, 0); - } - if ((prevRect.width() > 0) && (prevRect.height() > 0)) - buffer->setHasAlpha(true); - } - } - } - - // Update our status to be partially complete. - buffer->setStatus(RGBA32Buffer::FramePartial); - - // Reset the alpha pixel tracker for this frame. - m_currentBufferSawAlpha = false; - return true; -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h deleted file mode 100644 index 64240d4..0000000 --- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. - */ - -#ifndef GIFImageDecoder_h -#define GIFImageDecoder_h - -#include "ImageDecoder.h" -#include <wtf/OwnPtr.h> - -struct GIFImageReader; - -namespace WebCore { - - // This class decodes the GIF image format. - class GIFImageDecoder : public ImageDecoder { - public: - GIFImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - virtual ~GIFImageDecoder(); - - enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery }; - - // ImageDecoder - virtual String filenameExtension() const { return "gif"; } - virtual void setData(SharedBuffer* data, bool allDataReceived); - virtual bool isSizeAvailable(); - virtual bool setSize(int width, int height); - virtual size_t frameCount(); - virtual int repetitionCount() const; - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid - // accessing deleted memory, especially when calling this from inside - // GIFImageReader! - virtual bool setFailed(); - virtual void clearFrameBufferCache(size_t clearBeforeFrame); - - // Callbacks from the GIF reader. - void decodingHalted(unsigned bytesLeft); - bool haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels); - bool frameComplete(unsigned frameIndex, unsigned frameDuration, RGBA32Buffer::FrameDisposalMethod disposalMethod); - void gifComplete(); - - private: - // If the query is GIFFullQuery, decodes the image up to (but not - // including) |haltAtFrame|. Otherwise, decodes as much as is needed to - // answer the query, ignoring bitmap data. If decoding fails but there - // is no more data coming, sets the "decode failure" flag. - void decode(unsigned haltAtFrame, GIFQuery); - - // Called to initialize the frame buffer with the given index, based on - // the previous frame's disposal method. Returns true on success. On - // failure, this will mark the image as failed. - bool initFrameBuffer(unsigned frameIndex); - - bool m_alreadyScannedThisDataForFrameCount; - bool m_currentBufferSawAlpha; - mutable int m_repetitionCount; - OwnPtr<GIFImageReader> m_reader; - unsigned m_readOffset; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp b/WebCore/platform/image-decoders/gif/GIFImageReader.cpp deleted file mode 100644 index 1e033a3..0000000 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.cpp +++ /dev/null @@ -1,925 +0,0 @@ -/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Chris Saari <saari@netscape.com> - * Apple Computer - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/* -The Graphics Interchange Format(c) is the copyright property of CompuServe -Incorporated. Only CompuServe Incorporated is authorized to define, redefine, -enhance, alter, modify or change in any way the definition of the format. - -CompuServe Incorporated hereby grants a limited, non-exclusive, royalty-free -license for the use of the Graphics Interchange Format(sm) in computer -software; computer software utilizing GIF(sm) must acknowledge ownership of the -Graphics Interchange Format and its Service Mark by CompuServe Incorporated, in -User and Technical Documentation. Computer software utilizing GIF, which is -distributed or may be distributed without User or Technical Documentation must -display to the screen or printer a message acknowledging ownership of the -Graphics Interchange Format and the Service Mark by CompuServe Incorporated; in -this case, the acknowledgement may be displayed in an opening screen or leading -banner, or a closing screen or trailing banner. A message such as the following -may be used: - - "The Graphics Interchange Format(c) is the Copyright property of - CompuServe Incorporated. GIF(sm) is a Service Mark property of - CompuServe Incorporated." - -For further information, please contact : - - CompuServe Incorporated - Graphics Technology Department - 5000 Arlington Center Boulevard - Columbus, Ohio 43220 - U. S. A. - -CompuServe Incorporated maintains a mailing list with all those individuals and -organizations who wish to receive copies of this document when it is corrected -or revised. This service is offered free of charge; please provide us with your -mailing address. -*/ - -#include "config.h" -#include "GIFImageReader.h" - -#include <string.h> -#include "GIFImageDecoder.h" -#include "ImageSource.h" - -using WebCore::GIFImageDecoder; - -// Define the Mozilla macro setup so that we can leave the macros alone. -#define PR_BEGIN_MACRO do { -#define PR_END_MACRO } while (0) - -/* - * GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's' - * - * Note, the hold will never need to be bigger than 256 bytes to gather up in the hold, - * as each GIF block (except colormaps) can never be bigger than 256 bytes. - * Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap. - * So a fixed buffer in GIFImageReader is good enough. - * This buffer is only needed to copy left-over data from one GifWrite call to the next - */ -#define GETN(n,s) \ - PR_BEGIN_MACRO \ - bytes_to_consume = (n); \ - state = (s); \ - PR_END_MACRO - -/* Get a 16-bit value stored in little-endian format */ -#define GETINT16(p) ((p)[1]<<8|(p)[0]) - -//****************************************************************************** -// Send the data to the display front-end. -bool GIFImageReader::output_row() -{ - GIFFrameReader* gs = frame_reader; - - int drow_start, drow_end; - - drow_start = drow_end = gs->irow; - - /* - * Haeberli-inspired hack for interlaced GIFs: Replicate lines while - * displaying to diminish the "venetian-blind" effect as the image is - * loaded. Adjust pixel vertical positions to avoid the appearance of the - * image crawling up the screen as successive passes are drawn. - */ - if (gs->progressive_display && gs->interlaced && gs->ipass < 4) { - unsigned row_dup = 0, row_shift = 0; - - switch (gs->ipass) { - case 1: - row_dup = 7; - row_shift = 3; - break; - case 2: - row_dup = 3; - row_shift = 1; - break; - case 3: - row_dup = 1; - row_shift = 0; - break; - default: - break; - } - - drow_start -= row_shift; - drow_end = drow_start + row_dup; - - /* Extend if bottom edge isn't covered because of the shift upward. */ - if (((gs->height - 1) - drow_end) <= row_shift) - drow_end = gs->height - 1; - - /* Clamp first and last rows to upper and lower edge of image. */ - if (drow_start < 0) - drow_start = 0; - if ((unsigned)drow_end >= gs->height) - drow_end = gs->height - 1; - } - - /* Protect against too much image data */ - if ((unsigned)drow_start >= gs->height) - return true; - - // CALLBACK: Let the client know we have decoded a row. - if (clientptr && frame_reader && - !clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_reader->rowend, - drow_start, drow_end - drow_start + 1, - gs->progressive_display && gs->interlaced && gs->ipass > 1)) - return false; - - gs->rowp = gs->rowbuf; - - if (!gs->interlaced) - gs->irow++; - else { - do { - switch (gs->ipass) - { - case 1: - gs->irow += 8; - if (gs->irow >= gs->height) { - gs->ipass++; - gs->irow = 4; - } - break; - - case 2: - gs->irow += 8; - if (gs->irow >= gs->height) { - gs->ipass++; - gs->irow = 2; - } - break; - - case 3: - gs->irow += 4; - if (gs->irow >= gs->height) { - gs->ipass++; - gs->irow = 1; - } - break; - - case 4: - gs->irow += 2; - if (gs->irow >= gs->height){ - gs->ipass++; - gs->irow = 0; - } - break; - - default: - break; - } - } while (gs->irow > (gs->height - 1)); - } - - return true; -} - -//****************************************************************************** -/* Perform Lempel-Ziv-Welch decoding */ -bool GIFImageReader::do_lzw(const unsigned char *q) -{ - GIFFrameReader* gs = frame_reader; - if (!gs) - return true; - - int code; - int incode; - const unsigned char *ch; - - /* Copy all the decoder state variables into locals so the compiler - * won't worry about them being aliased. The locals will be homed - * back into the GIF decoder structure when we exit. - */ - int avail = gs->avail; - int bits = gs->bits; - int cnt = count; - int codesize = gs->codesize; - int codemask = gs->codemask; - int oldcode = gs->oldcode; - int clear_code = gs->clear_code; - unsigned char firstchar = gs->firstchar; - int datum = gs->datum; - - if (!gs->prefix) { - gs->prefix = new unsigned short[MAX_BITS]; - memset(gs->prefix, 0, MAX_BITS * sizeof(short)); - } - - unsigned short *prefix = gs->prefix; - unsigned char *stackp = gs->stackp; - unsigned char *suffix = gs->suffix; - unsigned char *stack = gs->stack; - unsigned char *rowp = gs->rowp; - unsigned char *rowend = gs->rowend; - unsigned rows_remaining = gs->rows_remaining; - - if (rowp == rowend) - return true; - -#define OUTPUT_ROW \ - PR_BEGIN_MACRO \ - if (!output_row()) \ - return false; \ - rows_remaining--; \ - rowp = frame_reader->rowp; \ - if (!rows_remaining) \ - goto END; \ - PR_END_MACRO - - for (ch = q; cnt-- > 0; ch++) - { - /* Feed the next byte into the decoder's 32-bit input buffer. */ - datum += ((int) *ch) << bits; - bits += 8; - - /* Check for underflow of decoder's 32-bit input buffer. */ - while (bits >= codesize) - { - /* Get the leading variable-length symbol from the data stream */ - code = datum & codemask; - datum >>= codesize; - bits -= codesize; - - /* Reset the dictionary to its original state, if requested */ - if (code == clear_code) { - codesize = gs->datasize + 1; - codemask = (1 << codesize) - 1; - avail = clear_code + 2; - oldcode = -1; - continue; - } - - /* Check for explicit end-of-stream code */ - if (code == (clear_code + 1)) { - /* end-of-stream should only appear after all image data */ - if (!rows_remaining) - return true; - return clientptr ? clientptr->setFailed() : false; - } - - if (oldcode == -1) { - *rowp++ = suffix[code]; - if (rowp == rowend) - OUTPUT_ROW; - - firstchar = oldcode = code; - continue; - } - - incode = code; - if (code >= avail) { - *stackp++ = firstchar; - code = oldcode; - - if (stackp == stack + MAX_BITS) - return clientptr ? clientptr->setFailed() : false; - } - - while (code >= clear_code) - { - if (code >= MAX_BITS || code == prefix[code]) - return clientptr ? clientptr->setFailed() : false; - - // Even though suffix[] only holds characters through suffix[avail - 1], - // allowing code >= avail here lets us be more tolerant of malformed - // data. As long as code < MAX_BITS, the only risk is a garbled image, - // which is no worse than refusing to display it. - *stackp++ = suffix[code]; - code = prefix[code]; - - if (stackp == stack + MAX_BITS) - return clientptr ? clientptr->setFailed() : false; - } - - *stackp++ = firstchar = suffix[code]; - - /* Define a new codeword in the dictionary. */ - if (avail < 4096) { - prefix[avail] = oldcode; - suffix[avail] = firstchar; - avail++; - - /* If we've used up all the codewords of a given length - * increase the length of codewords by one bit, but don't - * exceed the specified maximum codeword size of 12 bits. - */ - if (((avail & codemask) == 0) && (avail < 4096)) { - codesize++; - codemask += avail; - } - } - oldcode = incode; - - /* Copy the decoded data out to the scanline buffer. */ - do { - *rowp++ = *--stackp; - if (rowp == rowend) { - OUTPUT_ROW; - } - } while (stackp > stack); - } - } - - END: - - /* Home the local copies of the GIF decoder state variables */ - gs->avail = avail; - gs->bits = bits; - gs->codesize = codesize; - gs->codemask = codemask; - count = cnt; - gs->oldcode = oldcode; - gs->firstchar = firstchar; - gs->datum = datum; - gs->stackp = stackp; - gs->rowp = rowp; - gs->rows_remaining = rows_remaining; - - return true; -} - - -/******************************************************************************/ -/* - * process data arriving from the stream for the gif decoder - */ - -bool GIFImageReader::read(const unsigned char *buf, unsigned len, - GIFImageDecoder::GIFQuery query, unsigned haltAtFrame) -{ - if (!len) { - // No new data has come in since the last call, just ignore this call. - return true; - } - - const unsigned char *q = buf; - - // Add what we have so far to the block - // If previous call to me left something in the hold first complete current block - // Or if we are filling the colormaps, first complete the colormap - unsigned char* p = 0; - if (state == gif_global_colormap) - p = global_colormap; - else if (state == gif_image_colormap) - p = frame_reader ? frame_reader->local_colormap : 0; - else if (bytes_in_hold) - p = hold; - else - p = 0; - - if (p || (state == gif_global_colormap) || (state == gif_image_colormap)) { - // Add what we have sofar to the block - unsigned l = len < bytes_to_consume ? len : bytes_to_consume; - if (p) - memcpy(p + bytes_in_hold, buf, l); - - if (l < bytes_to_consume) { - // Not enough in 'buf' to complete current block, get more - bytes_in_hold += l; - bytes_to_consume -= l; - if (clientptr) - clientptr->decodingHalted(0); - return false; - } - // Reset hold buffer count - bytes_in_hold = 0; - // Point 'q' to complete block in hold (or in colormap) - q = p; - } - - // Invariant: - // 'q' is start of current to be processed block (hold, colormap or buf) - // 'bytes_to_consume' is number of bytes to consume from 'buf' - // 'buf' points to the bytes to be consumed from the input buffer - // 'len' is number of bytes left in input buffer from position 'buf'. - // At entrance of the for loop will 'buf' will be moved 'bytes_to_consume' - // to point to next buffer, 'len' is adjusted accordingly. - // So that next round in for loop, q gets pointed to the next buffer. - - for (;len >= bytes_to_consume; q=buf) { - // Eat the current block from the buffer, q keeps pointed at current block - buf += bytes_to_consume; - len -= bytes_to_consume; - - switch (state) - { - case gif_lzw: - if (!do_lzw(q)) - return false; // If do_lzw() encountered an error, it has already called - // clientptr->setFailed(). - GETN(1, gif_sub_block); - break; - - case gif_lzw_start: - { - /* Initialize LZW parser/decoder */ - int datasize = *q; - // Since we use a codesize of 1 more than the datasize, we need to ensure - // that our datasize is strictly less than the MAX_LZW_BITS value (12). - // This sets the largest possible codemask correctly at 4095. - if (datasize >= MAX_LZW_BITS) - return clientptr ? clientptr->setFailed() : false; - int clear_code = 1 << datasize; - if (clear_code >= MAX_BITS) - return clientptr ? clientptr->setFailed() : false; - - if (frame_reader) { - frame_reader->datasize = datasize; - frame_reader->clear_code = clear_code; - frame_reader->avail = frame_reader->clear_code + 2; - frame_reader->oldcode = -1; - frame_reader->codesize = frame_reader->datasize + 1; - frame_reader->codemask = (1 << frame_reader->codesize) - 1; - - frame_reader->datum = frame_reader->bits = 0; - - /* init the tables */ - if (!frame_reader->suffix) - frame_reader->suffix = new unsigned char[MAX_BITS]; - // Clearing the whole suffix table lets us be more tolerant of bad data. - memset(frame_reader->suffix, 0, MAX_BITS); - for (int i = 0; i < frame_reader->clear_code; i++) - frame_reader->suffix[i] = i; - - if (!frame_reader->stack) - frame_reader->stack = new unsigned char[MAX_BITS]; - frame_reader->stackp = frame_reader->stack; - } - - GETN(1, gif_sub_block); - } - break; - - /* All GIF files begin with "GIF87a" or "GIF89a" */ - case gif_type: - { - if (!strncmp((char*)q, "GIF89a", 6)) - version = 89; - else if (!strncmp((char*)q, "GIF87a", 6)) - version = 87; - else - return clientptr ? clientptr->setFailed() : false; - GETN(7, gif_global_header); - } - break; - - case gif_global_header: - { - /* This is the height and width of the "screen" or - * frame into which images are rendered. The - * individual images can be smaller than the - * screen size and located with an origin anywhere - * within the screen. - */ - - screen_width = GETINT16(q); - screen_height = GETINT16(q + 2); - - // CALLBACK: Inform the decoderplugin of our size. - if (clientptr && !clientptr->setSize(screen_width, screen_height)) - return false; - - screen_bgcolor = q[5]; - global_colormap_size = 2<<(q[4]&0x07); - - if ((q[4] & 0x80) && global_colormap_size > 0) { /* global map */ - // Get the global colormap - const unsigned size = 3*global_colormap_size; - - // Malloc the color map, but only if we're not just counting frames. - if (query != GIFImageDecoder::GIFFrameCountQuery) - global_colormap = new unsigned char[size]; - - if (len < size) { - // Use 'hold' pattern to get the global colormap - GETN(size, gif_global_colormap); - break; - } - - // Copy everything and go directly to gif_image_start. - if (global_colormap) - memcpy(global_colormap, buf, size); - buf += size; - len -= size; - } - - GETN(1, gif_image_start); - - // q[6] = Pixel Aspect Ratio - // Not used - // float aspect = (float)((q[6] + 15) / 64.0); - } - break; - - case gif_global_colormap: - // Everything is already copied into global_colormap - GETN(1, gif_image_start); - break; - - case gif_image_start: - { - if (*q == ';') { /* terminator */ - GETN(0, gif_done); - break; - } - - if (*q == '!') { /* extension */ - GETN(2, gif_extension); - break; - } - - /* If we get anything other than ',' (image separator), '!' - * (extension), or ';' (trailer), there is extraneous data - * between blocks. The GIF87a spec tells us to keep reading - * until we find an image separator, but GIF89a says such - * a file is corrupt. We follow GIF89a and bail out. */ - if (*q != ',') - return clientptr ? clientptr->setFailed() : false; - - GETN(9, gif_image_header); - } - break; - - case gif_extension: - { - int len = count = q[1]; - gstate es = gif_skip_block; - - switch (*q) - { - case 0xf9: - es = gif_control_extension; - break; - - case 0x01: - // ignoring plain text extension - break; - - case 0xff: - es = gif_application_extension; - break; - - case 0xfe: - es = gif_consume_comment; - break; - } - - if (len) - GETN(len, es); - else - GETN(1, gif_image_start); - } - break; - - case gif_consume_block: - if (!*q) - GETN(1, gif_image_start); - else - GETN(*q, gif_skip_block); - break; - - case gif_skip_block: - GETN(1, gif_consume_block); - break; - - case gif_control_extension: - { - if (query != GIFImageDecoder::GIFFrameCountQuery) { - if (!frame_reader) - frame_reader = new GIFFrameReader(); - } - - if (frame_reader) { - if (*q & 0x1) { - frame_reader->tpixel = q[3]; - frame_reader->is_transparent = true; - } else { - frame_reader->is_transparent = false; - // ignoring gfx control extension - } - // NOTE: This relies on the values in the FrameDisposalMethod enum - // matching those in the GIF spec! - frame_reader->disposal_method = (WebCore::RGBA32Buffer::FrameDisposalMethod)(((*q) >> 2) & 0x7); - // Some specs say 3rd bit (value 4), other specs say value 3 - // Let's choose 3 (the more popular) - if (frame_reader->disposal_method == 4) - frame_reader->disposal_method = WebCore::RGBA32Buffer::DisposeOverwritePrevious; - frame_reader->delay_time = GETINT16(q + 1) * 10; - } - GETN(1, gif_consume_block); - } - break; - - case gif_comment_extension: - { - if (*q) - GETN(*q, gif_consume_comment); - else - GETN(1, gif_image_start); - } - break; - - case gif_consume_comment: - GETN(1, gif_comment_extension); - break; - - case gif_application_extension: - /* Check for netscape application extension */ - if (!strncmp((char*)q, "NETSCAPE2.0", 11) || - !strncmp((char*)q, "ANIMEXTS1.0", 11)) - GETN(1, gif_netscape_extension_block); - else - GETN(1, gif_consume_block); - break; - - /* Netscape-specific GIF extension: animation looping */ - case gif_netscape_extension_block: - if (*q) - GETN(*q, gif_consume_netscape_extension); - else - GETN(1, gif_image_start); - break; - - /* Parse netscape-specific application extensions */ - case gif_consume_netscape_extension: - { - int netscape_extension = q[0] & 7; - - /* Loop entire animation specified # of times. Only read the - loop count during the first iteration. */ - if (netscape_extension == 1) { - loop_count = GETINT16(q + 1); - - /* Zero loop count is infinite animation loop request */ - if (loop_count == 0) - loop_count = WebCore::cAnimationLoopInfinite; - - GETN(1, gif_netscape_extension_block); - } - /* Wait for specified # of bytes to enter buffer */ - else if (netscape_extension == 2) { - // Don't do this, this extension doesn't exist (isn't used at all) - // and doesn't do anything, as our streaming/buffering takes care of it all... - // See: http://semmix.pl/color/exgraf/eeg24.htm - GETN(1, gif_netscape_extension_block); - } else { - // 0,3-7 are yet to be defined netscape extension codes - return clientptr ? clientptr->setFailed() : false; - } - - break; - } - - case gif_image_header: - { - unsigned height, width, x_offset, y_offset; - - /* Get image offsets, with respect to the screen origin */ - x_offset = GETINT16(q); - y_offset = GETINT16(q + 2); - - /* Get image width and height. */ - width = GETINT16(q + 4); - height = GETINT16(q + 6); - - /* Work around broken GIF files where the logical screen - * size has weird width or height. We assume that GIF87a - * files don't contain animations. - */ - if ((images_decoded == 0) && - ((screen_height < height) || (screen_width < width) || - (version == 87))) - { - screen_height = height; - screen_width = width; - x_offset = 0; - y_offset = 0; - - // CALLBACK: Inform the decoderplugin of our size. - if (clientptr && !clientptr->setSize(screen_width, screen_height)) - return false; - } - - /* Work around more broken GIF files that have zero image - width or height */ - if (!height || !width) { - height = screen_height; - width = screen_width; - if (!height || !width) - return clientptr ? clientptr->setFailed() : false; - } - - if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == images_decoded) { - // The decoder needs to stop. Hand back the number of bytes we consumed from - // buffer minus 9 (the amount we consumed to read the header). - if (clientptr) - clientptr->decodingHalted(len + 9); - GETN(9, gif_image_header); - return true; - } - - images_count = images_decoded + 1; - - if (query == GIFImageDecoder::GIFFullQuery && !frame_reader) - frame_reader = new GIFFrameReader(); - - if (frame_reader) { - frame_reader->x_offset = x_offset; - frame_reader->y_offset = y_offset; - frame_reader->height = height; - frame_reader->width = width; - - /* This case will never be taken if this is the first image */ - /* being decoded. If any of the later images are larger */ - /* than the screen size, we need to reallocate buffers. */ - if (screen_width < width) { - /* XXX Deviant! */ - - delete []frame_reader->rowbuf; - screen_width = width; - frame_reader->rowbuf = new unsigned char[screen_width]; - } else if (!frame_reader->rowbuf) { - frame_reader->rowbuf = new unsigned char[screen_width]; - } - - if (!frame_reader->rowbuf) - return clientptr ? clientptr->setFailed() : false; - if (screen_height < height) - screen_height = height; - - if (q[8] & 0x40) { - frame_reader->interlaced = true; - frame_reader->ipass = 1; - } else { - frame_reader->interlaced = false; - frame_reader->ipass = 0; - } - - if (images_decoded == 0) { - frame_reader->progressive_display = true; - } else { - /* Overlaying interlaced, transparent GIFs over - existing image data using the Haeberli display hack - requires saving the underlying image in order to - avoid jaggies at the transparency edges. We are - unprepared to deal with that, so don't display such - images progressively */ - frame_reader->progressive_display = false; - } - - /* Clear state from last image */ - frame_reader->irow = 0; - frame_reader->rows_remaining = frame_reader->height; - frame_reader->rowend = frame_reader->rowbuf + frame_reader->width; - frame_reader->rowp = frame_reader->rowbuf; - - /* bits per pixel is q[8]&0x07 */ - } - - if (q[8] & 0x80) /* has a local colormap? */ - { - int num_colors = 2 << (q[8] & 0x7); - const unsigned size = 3*num_colors; - unsigned char *map = frame_reader ? frame_reader->local_colormap : 0; - if (frame_reader && (!map || (num_colors > frame_reader->local_colormap_size))) { - delete []map; - map = new unsigned char[size]; - if (!map) - return clientptr ? clientptr->setFailed() : false; - } - - /* Switch to the new local palette after it loads */ - if (frame_reader) { - frame_reader->local_colormap = map; - frame_reader->local_colormap_size = num_colors; - frame_reader->is_local_colormap_defined = true; - } - - if (len < size) { - // Use 'hold' pattern to get the image colormap - GETN(size, gif_image_colormap); - break; - } - // Copy everything and directly go to gif_lzw_start - if (frame_reader) - memcpy(frame_reader->local_colormap, buf, size); - buf += size; - len -= size; - } else if (frame_reader) { - /* Switch back to the global palette */ - frame_reader->is_local_colormap_defined = false; - } - GETN(1, gif_lzw_start); - } - break; - - case gif_image_colormap: - // Everything is already copied into local_colormap - GETN(1, gif_lzw_start); - break; - - case gif_sub_block: - { - if ((count = *q) != 0) - /* Still working on the same image: Process next LZW data block */ - { - /* Make sure there are still rows left. If the GIF data */ - /* is corrupt, we may not get an explicit terminator. */ - if (frame_reader && frame_reader->rows_remaining == 0) { - /* This is an illegal GIF, but we remain tolerant. */ - GETN(1, gif_sub_block); - } - GETN(count, gif_lzw); - } - else - /* See if there are any more images in this sequence. */ - { - images_decoded++; - - // CALLBACK: The frame is now complete. - if (clientptr && frame_reader && !clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method)) - return false; // frameComplete() has already called - // clientptr->setFailed(). - - /* Clear state from this image */ - if (frame_reader) { - frame_reader->is_local_colormap_defined = false; - frame_reader->is_transparent = false; - } - - GETN(1, gif_image_start); - } - } - break; - - case gif_done: - // When the GIF is done, we can stop. - if (clientptr) - clientptr->gifComplete(); - return true; - - // We shouldn't ever get here. - default: - break; - } - } - - // Copy the leftover into gs->hold - bytes_in_hold = len; - if (len) { - // Add what we have sofar to the block - unsigned char* p; - if (state == gif_global_colormap) - p = global_colormap; - else if (state == gif_image_colormap) - p = frame_reader ? frame_reader->local_colormap : 0; - else - p = hold; - if (p) - memcpy(p, buf, len); - bytes_to_consume -= len; - } - - if (clientptr) - clientptr->decodingHalted(0); - return false; -} diff --git a/WebCore/platform/image-decoders/gif/GIFImageReader.h b/WebCore/platform/image-decoders/gif/GIFImageReader.h deleted file mode 100644 index be5be19..0000000 --- a/WebCore/platform/image-decoders/gif/GIFImageReader.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef GIFImageReader_h -#define GIFImageReader_h - -// Define ourselves as the clientPtr. Mozilla just hacked their C++ callback class into this old C decoder, -// so we will too. -#include "GIFImageDecoder.h" - -#define MAX_LZW_BITS 12 -#define MAX_BITS 4097 /* 2^MAX_LZW_BITS+1 */ -#define MAX_COLORS 256 -#define MAX_HOLD_SIZE 256 - -const int cLoopCountNotSeen = -2; - -/* gif2.h - The interface for the GIF87/89a decoder. -*/ -// List of possible parsing states -typedef enum { - gif_type, - gif_global_header, - gif_global_colormap, - gif_image_start, - gif_image_header, - gif_image_colormap, - gif_image_body, - gif_lzw_start, - gif_lzw, - gif_sub_block, - gif_extension, - gif_control_extension, - gif_consume_block, - gif_skip_block, - gif_done, - gif_comment_extension, - gif_application_extension, - gif_netscape_extension_block, - gif_consume_netscape_extension, - gif_consume_comment -} gstate; - -struct GIFFrameReader { - /* LZW decoder state machine */ - unsigned char *stackp; /* Current stack pointer */ - int datasize; - int codesize; - int codemask; - int clear_code; /* Codeword used to trigger dictionary reset */ - int avail; /* Index of next available slot in dictionary */ - int oldcode; - unsigned char firstchar; - int bits; /* Number of unread bits in "datum" */ - int datum; /* 32-bit input buffer */ - - /* Output state machine */ - int ipass; /* Interlace pass; Ranges 1-4 if interlaced. */ - unsigned int rows_remaining; /* Rows remaining to be output */ - unsigned int irow; /* Current output row, starting at zero */ - unsigned char *rowbuf; /* Single scanline temporary buffer */ - unsigned char *rowend; /* Pointer to end of rowbuf */ - unsigned char *rowp; /* Current output pointer */ - - /* Parameters for image frame currently being decoded */ - unsigned int x_offset, y_offset; /* With respect to "screen" origin */ - unsigned int height, width; - int tpixel; /* Index of transparent pixel */ - WebCore::RGBA32Buffer::FrameDisposalMethod disposal_method; /* Restore to background, leave in place, etc.*/ - unsigned char *local_colormap; /* Per-image colormap */ - int local_colormap_size; /* Size of local colormap array. */ - - bool is_local_colormap_defined : 1; - bool progressive_display : 1; /* If TRUE, do Haeberli interlace hack */ - bool interlaced : 1; /* TRUE, if scanlines arrive interlaced order */ - bool is_transparent : 1; /* TRUE, if tpixel is valid */ - - unsigned delay_time; /* Display time, in milliseconds, - for this image in a multi-image GIF */ - - - unsigned short* prefix; /* LZW decoding tables */ - unsigned char* suffix; /* LZW decoding tables */ - unsigned char* stack; /* Base of LZW decoder stack */ - - - GIFFrameReader() { - stackp = 0; - datasize = codesize = codemask = clear_code = avail = oldcode = 0; - firstchar = 0; - bits = datum = 0; - ipass = 0; - rows_remaining = irow = 0; - rowbuf = rowend = rowp = 0; - - x_offset = y_offset = width = height = 0; - tpixel = 0; - disposal_method = WebCore::RGBA32Buffer::DisposeNotSpecified; - - local_colormap = 0; - local_colormap_size = 0; - is_local_colormap_defined = progressive_display = is_transparent = interlaced = false; - - delay_time = 0; - - prefix = 0; - suffix = stack = 0; - } - - ~GIFFrameReader() { - delete []rowbuf; - delete []local_colormap; - delete []prefix; - delete []suffix; - delete []stack; - } -}; - -struct GIFImageReader { - WebCore::GIFImageDecoder* clientptr; - /* Parsing state machine */ - gstate state; /* Current decoder master state */ - unsigned bytes_to_consume; /* Number of bytes to accumulate */ - unsigned bytes_in_hold; /* bytes accumulated so far*/ - unsigned char hold[MAX_HOLD_SIZE]; /* Accumulation buffer */ - unsigned char* global_colormap; /* (3* MAX_COLORS in size) Default colormap if local not supplied, 3 bytes for each color */ - - /* Global (multi-image) state */ - int screen_bgcolor; /* Logical screen background color */ - int version; /* Either 89 for GIF89 or 87 for GIF87 */ - unsigned screen_width; /* Logical screen width & height */ - unsigned screen_height; - int global_colormap_size; /* Size of global colormap array. */ - unsigned images_decoded; /* Counts completed frames for animated GIFs */ - int images_count; /* Counted all frames seen so far (including incomplete frames) */ - int loop_count; /* Netscape specific extension block to control - the number of animation loops a GIF renders. */ - - // Not really global, but convenient to locate here. - int count; /* Remaining # bytes in sub-block */ - - GIFFrameReader* frame_reader; - - GIFImageReader(WebCore::GIFImageDecoder* client = 0) { - clientptr = client; - state = gif_type; - bytes_to_consume = 6; - bytes_in_hold = 0; - frame_reader = 0; - global_colormap = 0; - - screen_bgcolor = version = 0; - screen_width = screen_height = 0; - global_colormap_size = images_decoded = images_count = 0; - loop_count = cLoopCountNotSeen; - count = 0; - } - - ~GIFImageReader() { - delete []global_colormap; - global_colormap = 0; - delete frame_reader; - frame_reader = 0; - } - - bool read(const unsigned char * buf, unsigned int numbytes, - WebCore::GIFImageDecoder::GIFQuery query = WebCore::GIFImageDecoder::GIFFullQuery, unsigned haltAtFrame = -1); - -private: - bool output_row(); - bool do_lzw(const unsigned char *q); -}; - -#endif diff --git a/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp b/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp deleted file mode 100644 index 47302f7..0000000 --- a/WebCore/platform/image-decoders/haiku/ImageDecoderHaiku.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2010 Stephan Aßmus, <superstippi@gmx.de> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" - -#include <Bitmap.h> - -namespace WebCore { - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ - int bytesPerRow = width() * sizeof(PixelData); - OwnPtr<BBitmap> bitmap(new BBitmap(BRect(0, 0, width() - 1, height() - 1), 0, B_RGBA32, bytesPerRow)); - - const uint8* source = reinterpret_cast<const uint8*>(m_bytes); - uint8* destination = reinterpret_cast<uint8*>(bitmap->Bits()); - int h = height(); - int w = width(); - for (int y = 0; y < h; y++) { -#if 0 -// FIXME: Enable this conversion once Haiku has B_RGBA32P[remultiplied]... - memcpy(dst, source, bytesPerRow); -#else - const uint8* sourceHandle = source; - uint8* destinationHandle = destination; - for (int x = 0; x < w; x++) { - if (sourceHandle[3] == 255 || !sourceHandle[3]) { - destinationHandle[0] = sourceHandle[0]; - destinationHandle[1] = sourceHandle[1]; - destinationHandle[2] = sourceHandle[2]; - destinationHandle[3] = sourceHandle[3]; - } else { - destinationHandle[0] = static_cast<uint16>(sourceHandle[0]) * 255 / sourceHandle[3]; - destinationHandle[1] = static_cast<uint16>(sourceHandle[1]) * 255 / sourceHandle[3]; - destinationHandle[2] = static_cast<uint16>(sourceHandle[2]) * 255 / sourceHandle[3]; - destinationHandle[3] = sourceHandle[3]; - } - destinationHandle += 4; - sourceHandle += 4; - } -#endif - destination += bytesPerRow; - source += bytesPerRow; - } - - return bitmap.release(); -} - -} // namespace WebCore - diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp deleted file mode 100644 index 92a7dcf..0000000 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp +++ /dev/null @@ -1,315 +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" - -#include <algorithm> - -#include "BMPImageReader.h" -#include "PNGImageDecoder.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; - -ICOImageDecoder::ICOImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) - , m_decodedOffset(0) -{ -} - -ICOImageDecoder::~ICOImageDecoder() -{ -} - -void ICOImageDecoder::setData(SharedBuffer* data, bool allDataReceived) -{ - if (failed()) - return; - - ImageDecoder::setData(data, allDataReceived); - - for (BMPReaders::iterator i(m_bmpReaders.begin()); i != m_bmpReaders.end(); ++i) { - if (*i) - (*i)->setData(data); - } - for (size_t i = 0; i < m_pngDecoders.size(); ++i) - setDataForPNGDecoderAtIndex(i); -} - -bool ICOImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(0, true); - - return ImageDecoder::isSizeAvailable(); -} - -IntSize ICOImageDecoder::size() const -{ - return m_frameSize.isEmpty() ? ImageDecoder::size() : m_frameSize; -} - -IntSize ICOImageDecoder::frameSizeAtIndex(size_t index) const -{ - return (index && (index < m_dirEntries.size())) ? m_dirEntries[index].m_size : size(); -} - -bool ICOImageDecoder::setSize(unsigned width, unsigned height) -{ - // The size calculated inside the BMPImageReader had better match the one in - // the icon directory. - return m_frameSize.isEmpty() ? ImageDecoder::setSize(width, height) : ((IntSize(width, height) == m_frameSize) || setFailed()); -} - -size_t ICOImageDecoder::frameCount() -{ - decode(0, true); - if (m_frameBufferCache.isEmpty()) { - m_frameBufferCache.resize(m_dirEntries.size()); - for (size_t i = 0; i < m_dirEntries.size(); ++i) - m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha); - } - // CAUTION: We must not resize m_frameBufferCache again after this, as - // decodeAtIndex() may give a BMPImageReader a pointer to one of the - // entries. - return m_frameBufferCache.size(); -} - -RGBA32Buffer* ICOImageDecoder::frameBufferAtIndex(size_t index) -{ - // Ensure |index| is valid. - if (index >= frameCount()) - return 0; - - RGBA32Buffer* buffer = &m_frameBufferCache[index]; - if (buffer->status() != RGBA32Buffer::FrameComplete) - decode(index, false); - return buffer; -} - -bool ICOImageDecoder::setFailed() -{ - m_bmpReaders.clear(); - m_pngDecoders.clear(); - return ImageDecoder::setFailed(); -} - -// static -bool ICOImageDecoder::compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b) -{ - // Larger icons are better. After that, higher bit-depth icons are better. - const int aEntryArea = a.m_size.width() * a.m_size.height(); - const int bEntryArea = b.m_size.width() * b.m_size.height(); - return (aEntryArea == bEntryArea) ? (a.m_bitCount > b.m_bitCount) : (aEntryArea > bEntryArea); -} - -void ICOImageDecoder::setDataForPNGDecoderAtIndex(size_t index) -{ - if (!m_pngDecoders[index]) - return; - - const IconDirectoryEntry& dirEntry = m_dirEntries[index]; - // Copy out PNG data to a separate vector and send to the PNG decoder. - // FIXME: Save this copy by making the PNG decoder able to take an - // optional offset. - RefPtr<SharedBuffer> pngData(SharedBuffer::create(&m_data->data()[dirEntry.m_imageOffset], m_data->size() - dirEntry.m_imageOffset)); - m_pngDecoders[index]->setData(pngData.get(), isAllDataReceived()); -} - -void ICOImageDecoder::decode(size_t index, bool onlySize) -{ - if (failed()) - return; - - // If we couldn't decode the image but we've received all the data, decoding - // has failed. - if ((!decodeDirectory() || (!onlySize && !decodeAtIndex(index))) && isAllDataReceived()) - setFailed(); - // If we're done decoding this frame, we don't need the BMPImageReader or - // PNGImageDecoder anymore. (If we failed, these have already been - // cleared.) - else if ((m_frameBufferCache.size() > index) && (m_frameBufferCache[index].status() == RGBA32Buffer::FrameComplete)) { - m_bmpReaders[index].clear(); - m_pngDecoders[index].clear(); - } -} - -bool ICOImageDecoder::decodeDirectory() -{ - // Read and process directory. - if ((m_decodedOffset < sizeOfDirectory) && !processDirectory()) - return false; - - // Read and process directory entries. - return (m_decodedOffset >= (sizeOfDirectory + (m_dirEntries.size() * sizeOfDirEntry))) || processDirectoryEntries(); -} - -bool ICOImageDecoder::decodeAtIndex(size_t index) -{ - ASSERT(index < m_dirEntries.size()); - const IconDirectoryEntry& dirEntry = m_dirEntries[index]; - const ImageType imageType = imageTypeAtIndex(index); - if (imageType == Unknown) - return false; // Not enough data to determine image type yet. - - if (imageType == BMP) { - if (!m_bmpReaders[index]) { - // We need to have already sized m_frameBufferCache before this, and - // we must not resize it again later (see caution in frameCount()). - ASSERT(m_frameBufferCache.size() == m_dirEntries.size()); - m_bmpReaders[index].set(new BMPImageReader(this, dirEntry.m_imageOffset, 0, true)); - m_bmpReaders[index]->setData(m_data.get()); - m_bmpReaders[index]->setBuffer(&m_frameBufferCache[index]); - } - m_frameSize = dirEntry.m_size; - bool result = m_bmpReaders[index]->decodeBMP(false); - m_frameSize = IntSize(); - return result; - } - - if (!m_pngDecoders[index]) { - m_pngDecoders[index].set( - new PNGImageDecoder(m_premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, - m_ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied)); - setDataForPNGDecoderAtIndex(index); - } - // Fail if the size the PNGImageDecoder calculated does not match the size - // in the directory. - if (m_pngDecoders[index]->isSizeAvailable() && (m_pngDecoders[index]->size() != dirEntry.m_size)) - return setFailed(); - m_frameBufferCache[index] = *m_pngDecoders[index]->frameBufferAtIndex(0); - return !m_pngDecoders[index]->failed() || setFailed(); -} - -bool ICOImageDecoder::processDirectory() -{ - // Read directory. - ASSERT(!m_decodedOffset); - if (m_data->size() < sizeOfDirectory) - return false; - const uint16_t fileType = readUint16(2); - const uint16_t idCount = readUint16(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)) || (!idCount)) - return setFailed(); - - // Enlarge member vectors to hold all the entries. - m_dirEntries.resize(idCount); - m_bmpReaders.resize(idCount); - m_pngDecoders.resize(idCount); - return true; -} - -bool ICOImageDecoder::processDirectoryEntries() -{ - // Read directory entries. - ASSERT(m_decodedOffset == sizeOfDirectory); - if ((m_decodedOffset > m_data->size()) || ((m_data->size() - m_decodedOffset) < (m_dirEntries.size() * sizeOfDirEntry))) - return false; - for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) - *i = readDirectoryEntry(); // Updates m_decodedOffset. - - // Make sure the specified image offsets are past the end of the directory - // entries. - for (IconDirectoryEntries::iterator i(m_dirEntries.begin()); i != m_dirEntries.end(); ++i) { - if (i->m_imageOffset < m_decodedOffset) - return setFailed(); - } - - // Arrange frames in decreasing quality order. - std::sort(m_dirEntries.begin(), m_dirEntries.end(), compareEntries); - - // The image size is the size of the largest entry. - const IconDirectoryEntry& dirEntry = m_dirEntries.first(); - // Technically, this next call shouldn't be able to fail, since the width - // and height here are each <= 256, and |m_frameSize| is empty. - return setSize(dirEntry.m_size.width(), dirEntry.m_size.height()); -} - -ICOImageDecoder::IconDirectoryEntry ICOImageDecoder::readDirectoryEntry() -{ - // Read icon data. - // The casts to uint8_t in the next few lines are because that's the on-disk - // type of the width and height values. Storing them in ints (instead of - // matching uint8_ts) is so we can record dimensions of size 256 (which is - // what a zero byte really means). - int width = static_cast<uint8_t>(m_data->data()[m_decodedOffset]); - if (!width) - width = 256; - int height = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 1]); - if (!height) - height = 256; - IconDirectoryEntry entry; - entry.m_size = IntSize(width, height); - entry.m_bitCount = readUint16(6); - entry.m_imageOffset = readUint32(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.m_bitCount) { - int colorCount = static_cast<uint8_t>(m_data->data()[m_decodedOffset + 2]); - if (!colorCount) - colorCount = 256; // Vague in the spec, needed by real-world icons. - for (--colorCount; colorCount; colorCount >>= 1) - ++entry.m_bitCount; - } - - m_decodedOffset += sizeOfDirEntry; - return entry; -} - -ICOImageDecoder::ImageType ICOImageDecoder::imageTypeAtIndex(size_t index) -{ - // Check if this entry is a BMP or a PNG; we need 4 bytes to check the magic - // number. - ASSERT(index < m_dirEntries.size()); - const uint32_t imageOffset = m_dirEntries[index].m_imageOffset; - if ((imageOffset > m_data->size()) || ((m_data->size() - imageOffset) < 4)) - return Unknown; - return strncmp(&m_data->data()[imageOffset], "\x89PNG", 4) ? BMP : PNG; -} - -} diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h deleted file mode 100644 index c2af6a3..0000000 --- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h +++ /dev/null @@ -1,142 +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. - */ - -#ifndef ICOImageDecoder_h -#define ICOImageDecoder_h - -#include "BMPImageReader.h" - -namespace WebCore { - - class PNGImageDecoder; - - // This class decodes the ICO and CUR image formats. - class ICOImageDecoder : public ImageDecoder { - public: - ICOImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - virtual ~ICOImageDecoder(); - - // ImageDecoder - virtual String filenameExtension() const { return "ico"; } - virtual void setData(SharedBuffer*, bool allDataReceived); - virtual bool isSizeAvailable(); - virtual IntSize size() const; - virtual IntSize frameSizeAtIndex(size_t) const; - virtual bool setSize(unsigned width, unsigned height); - virtual size_t frameCount(); - virtual RGBA32Buffer* frameBufferAtIndex(size_t); - // CAUTION: setFailed() deletes all readers and decoders. Be careful to - // avoid accessing deleted memory, especially when calling this from - // inside BMPImageReader! - virtual bool setFailed(); - - private: - enum ImageType { - Unknown, - BMP, - PNG, - }; - - struct IconDirectoryEntry { - IntSize m_size; - uint16_t m_bitCount; - uint32_t m_imageOffset; - }; - - // Returns true if |a| is a preferable icon entry to |b|. - // Larger sizes, or greater bitdepths at the same size, are preferable. - static bool compareEntries(const IconDirectoryEntry& a, const IconDirectoryEntry& b); - - inline uint16_t readUint16(int offset) const - { - return BMPImageReader::readUint16(m_data.get(), m_decodedOffset + offset); - } - - inline uint32_t readUint32(int offset) const - { - return BMPImageReader::readUint32(m_data.get(), m_decodedOffset + offset); - } - - // If the desired PNGImageDecoder exists, gives it the appropriate data. - void setDataForPNGDecoderAtIndex(size_t); - - // Decodes the entry at |index|. If |onlySize| is true, stops decoding - // after calculating the image size. If decoding fails but there is no - // more data coming, sets the "decode failure" flag. - void decode(size_t index, bool onlySize); - - // Decodes the directory and directory entries at the beginning of the - // data, and initializes members. Returns true if all decoding - // succeeded. Once this returns true, all entries' sizes are known. - bool decodeDirectory(); - - // Decodes the specified entry. - bool decodeAtIndex(size_t); - - // Processes the ICONDIR at the beginning of the data. Returns true if - // the directory could be decoded. - bool processDirectory(); - - // Processes the ICONDIRENTRY records after the directory. Keeps the - // "best" entry as the one we'll decode. Returns true if the entries - // could be decoded. - bool processDirectoryEntries(); - - // Reads and returns a directory entry from the current offset into - // |data|. - IconDirectoryEntry readDirectoryEntry(); - - // Determines whether the desired entry is a BMP or PNG. Returns true - // if the type could be determined. - ImageType imageTypeAtIndex(size_t); - - // An index into |m_data| representing how much we've already decoded. - // Note that this only tracks data _this_ class decodes; once the - // BMPImageReader takes over this will not be updated further. - size_t m_decodedOffset; - - // The headers for the ICO. - typedef Vector<IconDirectoryEntry> IconDirectoryEntries; - IconDirectoryEntries m_dirEntries; - - // The image decoders for the various frames. - typedef Vector<OwnPtr<BMPImageReader> > BMPReaders; - BMPReaders m_bmpReaders; - typedef Vector<OwnPtr<PNGImageDecoder> > PNGDecoders; - PNGDecoders m_pngDecoders; - - // Valid only while a BMPImageReader is decoding, this holds the size - // for the particular entry being decoded. - IntSize m_frameSize; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp deleted file mode 100644 index 632d428..0000000 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. - * - * Portions are Copyright (C) 2001-6 mozilla.org - * - * Other contributors: - * Stuart Parmenter <stuart@mozilla.com> - * - * Copyright (C) 2007-2009 Torch Mobile, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. - */ - -#include "config.h" -#include "JPEGImageDecoder.h" -#include <stdio.h> // Needed by jpeglib.h for FILE. - -#if OS(WINCE) || PLATFORM(BREWMP_SIMULATOR) -// Remove warning: 'FAR' macro redefinition -#undef FAR - -// jmorecfg.h in libjpeg checks for XMD_H with the comment: "X11/xmd.h correctly defines INT32" -// fix INT32 redefinition error by pretending we are X11/xmd.h -#define XMD_H -#endif - -extern "C" { - -#include "jpeglib.h" - -#if USE(ICCJPEG) -#include "iccjpeg.h" -#endif - -} - -#include <setjmp.h> - -namespace WebCore { - -struct decoder_error_mgr { - struct jpeg_error_mgr pub; // "public" fields for IJG library - jmp_buf setjmp_buffer; // For handling catastropic errors -}; - -enum jstate { - JPEG_HEADER, // Reading JFIF headers - JPEG_START_DECOMPRESS, - JPEG_DECOMPRESS_PROGRESSIVE, // Output progressive pixels - JPEG_DECOMPRESS_SEQUENTIAL, // Output sequential pixels - JPEG_DONE, - JPEG_ERROR -}; - -void init_source(j_decompress_ptr jd); -boolean fill_input_buffer(j_decompress_ptr jd); -void skip_input_data(j_decompress_ptr jd, long num_bytes); -void term_source(j_decompress_ptr jd); -void error_exit(j_common_ptr cinfo); - -// Implementation of a JPEG src object that understands our state machine -struct decoder_source_mgr { - // public fields; must be first in this struct! - struct jpeg_source_mgr pub; - - JPEGImageReader* decoder; -}; - -static ColorProfile readColorProfile(jpeg_decompress_struct* info) -{ -#if USE(ICCJPEG) - JOCTET* profile; - unsigned int profileLength; - - if (!read_icc_profile(info, &profile, &profileLength)) - return ColorProfile(); - - ColorProfile colorProfile; - colorProfile.append(reinterpret_cast<char*>(profile), profileLength); - free(profile); - return colorProfile; -#else - return ColorProfile(); -#endif -} - -class JPEGImageReader -{ -public: - JPEGImageReader(JPEGImageDecoder* decoder) - : m_decoder(decoder) - , m_bufferLength(0) - , m_bytesToSkip(0) - , m_state(JPEG_HEADER) - , m_samples(0) - { - memset(&m_info, 0, sizeof(jpeg_decompress_struct)); - - // We set up the normal JPEG error routines, then override error_exit. - m_info.err = jpeg_std_error(&m_err.pub); - m_err.pub.error_exit = error_exit; - - // Allocate and initialize JPEG decompression object. - jpeg_create_decompress(&m_info); - - decoder_source_mgr* src = 0; - if (!m_info.src) { - src = (decoder_source_mgr*)fastCalloc(sizeof(decoder_source_mgr), 1); - if (!src) { - m_state = JPEG_ERROR; - return; - } - } - - m_info.src = (jpeg_source_mgr*)src; - - // Set up callback functions. - src->pub.init_source = init_source; - src->pub.fill_input_buffer = fill_input_buffer; - src->pub.skip_input_data = skip_input_data; - src->pub.resync_to_restart = jpeg_resync_to_restart; - src->pub.term_source = term_source; - src->decoder = this; - - // Enable these markers for the ICC color profile. - // Apparently there are 16 of these markers. I don't see anywhere in the header with this constant. - for (unsigned i = 0; i < 0xF; ++i) - jpeg_save_markers(&m_info, JPEG_APP0 + i, 0xFFFF); - } - - ~JPEGImageReader() - { - close(); - } - - void close() - { - decoder_source_mgr* src = (decoder_source_mgr*)m_info.src; - if (src) - fastFree(src); - m_info.src = 0; - - jpeg_destroy_decompress(&m_info); - } - - void skipBytes(long numBytes) - { - decoder_source_mgr* src = (decoder_source_mgr*)m_info.src; - long bytesToSkip = std::min(numBytes, (long)src->pub.bytes_in_buffer); - src->pub.bytes_in_buffer -= (size_t)bytesToSkip; - src->pub.next_input_byte += bytesToSkip; - - m_bytesToSkip = std::max(numBytes - bytesToSkip, static_cast<long>(0)); - } - - bool decode(const Vector<char>& data, bool onlySize) - { - m_decodingSizeOnly = onlySize; - - unsigned newByteCount = data.size() - m_bufferLength; - unsigned readOffset = m_bufferLength - m_info.src->bytes_in_buffer; - - m_info.src->bytes_in_buffer += newByteCount; - m_info.src->next_input_byte = (JOCTET*)(data.data()) + readOffset; - - // If we still have bytes to skip, try to skip those now. - if (m_bytesToSkip) - skipBytes(m_bytesToSkip); - - m_bufferLength = data.size(); - - // We need to do the setjmp here. Otherwise bad things will happen - if (setjmp(m_err.setjmp_buffer)) - return m_decoder->setFailed(); - - switch (m_state) { - case JPEG_HEADER: - // Read file parameters with jpeg_read_header(). - if (jpeg_read_header(&m_info, true) == JPEG_SUSPENDED) - return false; // I/O suspension. - - // Let libjpeg take care of gray->RGB and YCbCr->RGB conversions. - switch (m_info.jpeg_color_space) { - case JCS_GRAYSCALE: - case JCS_YCbCr: - // Grayscale images get "upsampled" by libjpeg. If we use - // their color profile, CoreGraphics will "upsample" them - // again, resulting in horizontal distortions. - m_decoder->setIgnoreGammaAndColorProfile(true); - // Note fall-through! - case JCS_RGB: - m_info.out_color_space = JCS_RGB; - break; - case JCS_CMYK: - case JCS_YCCK: - // jpeglib cannot convert these to rgb, but it can convert ycck - // to cmyk. - m_info.out_color_space = JCS_CMYK; - break; - default: - return m_decoder->setFailed(); - } - - // Don't allocate a giant and superfluous memory buffer when the - // image is a sequential JPEG. - m_info.buffered_image = jpeg_has_multiple_scans(&m_info); - - // Used to set up image size so arrays can be allocated. - jpeg_calc_output_dimensions(&m_info); - - // Make a one-row-high sample array that will go away when done with - // image. Always make it big enough to hold an RGB row. Since this - // uses the IJG memory manager, it must be allocated before the call - // to jpeg_start_compress(). - m_samples = (*m_info.mem->alloc_sarray)((j_common_ptr) &m_info, JPOOL_IMAGE, m_info.output_width * 4, 1); - - m_state = JPEG_START_DECOMPRESS; - - // We can fill in the size now that the header is available. - if (!m_decoder->setSize(m_info.image_width, m_info.image_height)) - return false; - - if (!m_decoder->ignoresGammaAndColorProfile()) - m_decoder->setColorProfile(readColorProfile(info())); - - if (m_decodingSizeOnly) { - // We can stop here. Reduce our buffer length and available - // data. - m_bufferLength -= m_info.src->bytes_in_buffer; - m_info.src->bytes_in_buffer = 0; - return true; - } - // FALL THROUGH - - case JPEG_START_DECOMPRESS: - // Set parameters for decompression. - // FIXME -- Should reset dct_method and dither mode for final pass - // of progressive JPEG. - m_info.dct_method = JDCT_ISLOW; - m_info.dither_mode = JDITHER_FS; - m_info.do_fancy_upsampling = true; - m_info.enable_2pass_quant = false; - m_info.do_block_smoothing = true; - - // Start decompressor. - if (!jpeg_start_decompress(&m_info)) - return false; // I/O suspension. - - // If this is a progressive JPEG ... - m_state = (m_info.buffered_image) ? JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; - // FALL THROUGH - - case JPEG_DECOMPRESS_SEQUENTIAL: - if (m_state == JPEG_DECOMPRESS_SEQUENTIAL) { - - if (!m_decoder->outputScanlines()) - return false; // I/O suspension. - - // If we've completed image output... - ASSERT(m_info.output_scanline == m_info.output_height); - m_state = JPEG_DONE; - } - // FALL THROUGH - - case JPEG_DECOMPRESS_PROGRESSIVE: - if (m_state == JPEG_DECOMPRESS_PROGRESSIVE) { - int status; - do { - status = jpeg_consume_input(&m_info); - } while ((status != JPEG_SUSPENDED) && (status != JPEG_REACHED_EOI)); - - for (;;) { - if (!m_info.output_scanline) { - int scan = m_info.input_scan_number; - - // If we haven't displayed anything yet - // (output_scan_number == 0) and we have enough data for - // a complete scan, force output of the last full scan. - if (!m_info.output_scan_number && (scan > 1) && (status != JPEG_REACHED_EOI)) - --scan; - - if (!jpeg_start_output(&m_info, scan)) - return false; // I/O suspension. - } - - if (m_info.output_scanline == 0xffffff) - m_info.output_scanline = 0; - - if (!m_decoder->outputScanlines()) { - if (!m_info.output_scanline) - // Didn't manage to read any lines - flag so we - // don't call jpeg_start_output() multiple times for - // the same scan. - m_info.output_scanline = 0xffffff; - return false; // I/O suspension. - } - - if (m_info.output_scanline == m_info.output_height) { - if (!jpeg_finish_output(&m_info)) - return false; // I/O suspension. - - if (jpeg_input_complete(&m_info) && (m_info.input_scan_number == m_info.output_scan_number)) - break; - - m_info.output_scanline = 0; - } - } - - m_state = JPEG_DONE; - } - // FALL THROUGH - - case JPEG_DONE: - // Finish decompression. - return jpeg_finish_decompress(&m_info); - - case JPEG_ERROR: - // We can get here if the constructor failed. - return m_decoder->setFailed(); - } - - return true; - } - - jpeg_decompress_struct* info() { return &m_info; } - JSAMPARRAY samples() const { return m_samples; } - JPEGImageDecoder* decoder() { return m_decoder; } - -private: - JPEGImageDecoder* m_decoder; - unsigned m_bufferLength; - int m_bytesToSkip; - bool m_decodingSizeOnly; - bool m_initialized; - - jpeg_decompress_struct m_info; - decoder_error_mgr m_err; - jstate m_state; - - JSAMPARRAY m_samples; -}; - -// Override the standard error method in the IJG JPEG decoder code. -void error_exit(j_common_ptr cinfo) -{ - // Return control to the setjmp point. - decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err; - longjmp(err->setjmp_buffer, -1); -} - -void init_source(j_decompress_ptr jd) -{ -} - -void skip_input_data(j_decompress_ptr jd, long num_bytes) -{ - decoder_source_mgr *src = (decoder_source_mgr *)jd->src; - src->decoder->skipBytes(num_bytes); -} - -boolean fill_input_buffer(j_decompress_ptr jd) -{ - // Our decode step always sets things up properly, so if this method is ever - // called, then we have hit the end of the buffer. A return value of false - // indicates that we have no data to supply yet. - return false; -} - -void term_source(j_decompress_ptr jd) -{ - decoder_source_mgr *src = (decoder_source_mgr *)jd->src; - src->decoder->decoder()->jpegComplete(); -} - -JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) -{ -} - -JPEGImageDecoder::~JPEGImageDecoder() -{ -} - -bool JPEGImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(true); - - return ImageDecoder::isSizeAvailable(); -} - -bool JPEGImageDecoder::setSize(unsigned width, unsigned height) -{ - if (!ImageDecoder::setSize(width, height)) - return false; - - prepareScaleDataIfNecessary(); - return true; -} - -RGBA32Buffer* JPEGImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index) - return 0; - - if (m_frameBufferCache.isEmpty()) { - m_frameBufferCache.resize(1); - m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); - } - - RGBA32Buffer& frame = m_frameBufferCache[0]; - if (frame.status() != RGBA32Buffer::FrameComplete) - decode(false); - return &frame; -} - -bool JPEGImageDecoder::setFailed() -{ - m_reader.clear(); - return ImageDecoder::setFailed(); -} - -bool JPEGImageDecoder::outputScanlines() -{ - if (m_frameBufferCache.isEmpty()) - return false; - - // Initialize the framebuffer if needed. - RGBA32Buffer& buffer = m_frameBufferCache[0]; - if (buffer.status() == RGBA32Buffer::FrameEmpty) { - if (!buffer.setSize(scaledSize().width(), scaledSize().height())) - return setFailed(); - buffer.setStatus(RGBA32Buffer::FramePartial); - buffer.setHasAlpha(false); - buffer.setColorProfile(m_colorProfile); - - // For JPEGs, the frame always fills the entire image. - buffer.setRect(IntRect(IntPoint(), size())); - } - - jpeg_decompress_struct* info = m_reader->info(); - JSAMPARRAY samples = m_reader->samples(); - - while (info->output_scanline < info->output_height) { - // jpeg_read_scanlines will increase the scanline counter, so we - // save the scanline before calling it. - int sourceY = info->output_scanline; - /* Request one scanline. Returns 0 or 1 scanlines. */ - if (jpeg_read_scanlines(info, samples, 1) != 1) - return false; - - int destY = scaledY(sourceY); - if (destY < 0) - continue; - int width = m_scaled ? m_scaledColumns.size() : info->output_width; - for (int x = 0; x < width; ++x) { - JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4); - if (info->out_color_space == JCS_RGB) - buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF); - else if (info->out_color_space == JCS_CMYK) { - // Source is 'Inverted CMYK', output is RGB. - // See: http://www.easyrgb.com/math.php?MATH=M12#text12 - // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb - // From CMYK to CMY: - // X = X * (1 - K ) + K [for X = C, M, or Y] - // Thus, from Inverted CMYK to CMY is: - // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK - // From CMY (0..1) to RGB (0..1): - // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar] - unsigned k = jsample[3]; - buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF); - } else { - ASSERT_NOT_REACHED(); - return setFailed(); - } - } - } - - return true; -} - -void JPEGImageDecoder::jpegComplete() -{ - if (m_frameBufferCache.isEmpty()) - return; - - // Hand back an appropriately sized buffer, even if the image ended up being - // empty. - m_frameBufferCache[0].setStatus(RGBA32Buffer::FrameComplete); -} - -void JPEGImageDecoder::decode(bool onlySize) -{ - if (failed()) - return; - - if (!m_reader) - m_reader.set(new JPEGImageReader(this)); - - // If we couldn't decode the image but we've received all the data, decoding - // has failed. - if (!m_reader->decode(m_data->buffer(), onlySize) && isAllDataReceived()) - setFailed(); - // If we're done decoding the image, we don't need the JPEGImageReader - // anymore. (If we failed, |m_reader| has already been cleared.) - else if (!m_frameBufferCache.isEmpty() && (m_frameBufferCache[0].status() == RGBA32Buffer::FrameComplete)) - m_reader.clear(); -} - -} diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h deleted file mode 100644 index 63f29ab..0000000 --- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008-2009 Torch Mobile, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. - */ - -#ifndef JPEGImageDecoder_h -#define JPEGImageDecoder_h - -#include "ImageDecoder.h" -#include <wtf/OwnPtr.h> - -namespace WebCore { - - class JPEGImageReader; - - // This class decodes the JPEG image format. - class JPEGImageDecoder : public ImageDecoder { - public: - JPEGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - virtual ~JPEGImageDecoder(); - - // ImageDecoder - virtual String filenameExtension() const { return "jpg"; } - virtual bool isSizeAvailable(); - virtual bool setSize(unsigned width, unsigned height); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - virtual bool supportsAlpha() const { return false; } - // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid - // accessing deleted memory, especially when calling this from inside - // JPEGImageReader! - virtual bool setFailed(); - - bool outputScanlines(); - void jpegComplete(); - - void setColorProfile(const ColorProfile& colorProfile) { m_colorProfile = colorProfile; } - - private: - // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. If decoding fails but there is no more - // data coming, sets the "decode failure" flag. - void decode(bool onlySize); - - OwnPtr<JPEGImageReader> m_reader; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/openvg/ImageDecoderOpenVG.cpp b/WebCore/platform/image-decoders/openvg/ImageDecoderOpenVG.cpp deleted file mode 100644 index 061c5ab..0000000 --- a/WebCore/platform/image-decoders/openvg/ImageDecoderOpenVG.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "ImageDecoder.h" - -#include "IntRect.h" -#include "IntSize.h" -#include "SurfaceOpenVG.h" -#include "TiledImageOpenVG.h" -#include "VGUtils.h" - -#if PLATFORM(EGL) -#include "EGLDisplayOpenVG.h" -#endif - -#include <openvg.h> - -namespace WebCore { - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ - static const VGImageFormat bufferFormat = VG_sARGB_8888_PRE; - // Save memory by using 16-bit images for fully opaque images. - const VGImageFormat imageFormat = hasAlpha() ? bufferFormat : VG_sRGB_565; - -#if PLATFORM(EGL) - EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent(); -#endif - - const IntSize vgMaxImageSize(vgGeti(VG_MAX_IMAGE_WIDTH), vgGeti(VG_MAX_IMAGE_HEIGHT)); - ASSERT_VG_NO_ERROR(); - - TiledImageOpenVG* tiledImage = new TiledImageOpenVG(IntSize(width(), height()), vgMaxImageSize); - - const int numColumns = tiledImage->numColumns(); - const int numRows = tiledImage->numRows(); - - for (int yIndex = 0; yIndex < numRows; ++yIndex) { - for (int xIndex = 0; xIndex < numColumns; ++xIndex) { - IntRect tileRect = tiledImage->tileRect(xIndex, yIndex); - VGImage image = vgCreateImage(imageFormat, - tileRect.width(), tileRect.height(), VG_IMAGE_QUALITY_FASTER); - ASSERT_VG_NO_ERROR(); - - PixelData* pixelData = const_cast<PixelData*>(m_bytes); - pixelData += (tileRect.y() * width()) + tileRect.x(); - - vgImageSubData(image, reinterpret_cast<unsigned char*>(pixelData), - width() * sizeof(PixelData), bufferFormat, - 0, 0, tileRect.width(), tileRect.height()); - ASSERT_VG_NO_ERROR(); - - tiledImage->setTile(xIndex, yIndex, image); - } - } - - return tiledImage; -} - -} diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp deleted file mode 100644 index 3fe4d3c..0000000 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. - * Copyright (C) 2007-2009 Torch Mobile, Inc. - * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. - * - * Portions are Copyright (C) 2001 mozilla.org - * - * Other contributors: - * Stuart Parmenter <stuart@mozilla.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. - */ - -#include "config.h" -#include "PNGImageDecoder.h" -#include "png.h" - -#if defined(PNG_LIBPNG_VER_MAJOR) && defined(PNG_LIBPNG_VER_MINOR) && (PNG_LIBPNG_VER_MAJOR > 1 || (PNG_LIBPNG_VER_MAJOR == 1 && PNG_LIBPNG_VER_MINOR >= 4)) -#define JMPBUF(png_ptr) png_jmpbuf(png_ptr) -#else -#define JMPBUF(png_ptr) png_ptr->jmpbuf -#endif - -namespace WebCore { - -// Gamma constants. -const double cMaxGamma = 21474.83; -const double cDefaultGamma = 2.2; -const double cInverseGamma = 0.45455; - -// Protect against large PNGs. See Mozilla's bug #251381 for more info. -const unsigned long cMaxPNGSize = 1000000UL; - -// Called if the decoding of the image fails. -static void PNGAPI decodingFailed(png_structp png, png_const_charp) -{ - longjmp(JMPBUF(png), 1); -} - -// Callbacks given to the read struct. The first is for warnings (we want to -// treat a particular warning as an error, which is why we have to register this -// callback). -static void PNGAPI decodingWarning(png_structp png, png_const_charp warningMsg) -{ - // Mozilla did this, so we will too. - // Convert a tRNS warning to be an error (see - // http://bugzilla.mozilla.org/show_bug.cgi?id=251381 ) - if (!strncmp(warningMsg, "Missing PLTE before tRNS", 24)) - png_error(png, warningMsg); -} - -// Called when we have obtained the header information (including the size). -static void PNGAPI headerAvailable(png_structp png, png_infop) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->headerAvailable(); -} - -// Called when a row is ready. -static void PNGAPI rowAvailable(png_structp png, png_bytep rowBuffer, png_uint_32 rowIndex, int interlacePass) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->rowAvailable(rowBuffer, rowIndex, interlacePass); -} - -// Called when we have completely finished decoding the image. -static void PNGAPI pngComplete(png_structp png, png_infop) -{ - static_cast<PNGImageDecoder*>(png_get_progressive_ptr(png))->pngComplete(); -} - -class PNGImageReader -{ -public: - PNGImageReader(PNGImageDecoder* decoder) - : m_readOffset(0) - , m_decodingSizeOnly(false) - , m_interlaceBuffer(0) - , m_hasAlpha(false) - , m_currentBufferSize(0) - { - m_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, decodingFailed, decodingWarning); - m_info = png_create_info_struct(m_png); - png_set_progressive_read_fn(m_png, decoder, headerAvailable, rowAvailable, pngComplete); - } - - ~PNGImageReader() - { - close(); - } - - void close() - { - if (m_png && m_info) - // This will zero the pointers. - png_destroy_read_struct(&m_png, &m_info, 0); - delete[] m_interlaceBuffer; - m_interlaceBuffer = 0; - m_readOffset = 0; - } - - unsigned currentBufferSize() const { return m_currentBufferSize; } - - bool decode(const SharedBuffer& data, bool sizeOnly) - { - m_decodingSizeOnly = sizeOnly; - PNGImageDecoder* decoder = static_cast<PNGImageDecoder*>(png_get_progressive_ptr(m_png)); - - // We need to do the setjmp here. Otherwise bad things will happen. - if (setjmp(JMPBUF(m_png))) - return decoder->setFailed(); - - const char* segment; - while (unsigned segmentLength = data.getSomeData(segment, m_readOffset)) { - m_readOffset += segmentLength; - m_currentBufferSize = m_readOffset; - png_process_data(m_png, m_info, reinterpret_cast<png_bytep>(const_cast<char*>(segment)), segmentLength); - // We explicitly specify the superclass isSizeAvailable() because we - // merely want to check if we've managed to set the size, not - // (recursively) trigger additional decoding if we haven't. - if (sizeOnly ? decoder->ImageDecoder::isSizeAvailable() : decoder->isComplete()) - return true; - } - return false; - } - - bool decodingSizeOnly() const { return m_decodingSizeOnly; } - png_structp pngPtr() const { return m_png; } - png_infop infoPtr() const { return m_info; } - png_bytep interlaceBuffer() const { return m_interlaceBuffer; } - bool hasAlpha() const { return m_hasAlpha; } - - void setReadOffset(unsigned offset) { m_readOffset = offset; } - void setHasAlpha(bool b) { m_hasAlpha = b; } - - void createInterlaceBuffer(int size) { m_interlaceBuffer = new png_byte[size]; } - -private: - unsigned m_readOffset; - bool m_decodingSizeOnly; - png_structp m_png; - png_infop m_info; - png_bytep m_interlaceBuffer; - bool m_hasAlpha; - unsigned m_currentBufferSize; -}; - -PNGImageDecoder::PNGImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) - , m_doNothingOnFailure(false) -{ -} - -PNGImageDecoder::~PNGImageDecoder() -{ -} - -bool PNGImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(true); - - return ImageDecoder::isSizeAvailable(); -} - -bool PNGImageDecoder::setSize(unsigned width, unsigned height) -{ - if (!ImageDecoder::setSize(width, height)) - return false; - - prepareScaleDataIfNecessary(); - return true; -} - -RGBA32Buffer* PNGImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index) - return 0; - - if (m_frameBufferCache.isEmpty()) { - m_frameBufferCache.resize(1); - m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); - } - - RGBA32Buffer& frame = m_frameBufferCache[0]; - if (frame.status() != RGBA32Buffer::FrameComplete) - decode(false); - return &frame; -} - -bool PNGImageDecoder::setFailed() -{ - if (m_doNothingOnFailure) - return false; - m_reader.clear(); - return ImageDecoder::setFailed(); -} - -static ColorProfile readColorProfile(png_structp png, png_infop info) -{ -#ifdef PNG_iCCP_SUPPORTED - char* profileName; - int compressionType; - char* profile; - png_uint_32 profileLength; - if (png_get_iCCP(png, info, &profileName, &compressionType, &profile, &profileLength)) { - ColorProfile colorProfile; - colorProfile.append(profile, profileLength); - return colorProfile; - } -#endif - return ColorProfile(); -} - -void PNGImageDecoder::headerAvailable() -{ - png_structp png = m_reader->pngPtr(); - png_infop info = m_reader->infoPtr(); - png_uint_32 width = png->width; - png_uint_32 height = png->height; - - // Protect against large images. - if (png->width > cMaxPNGSize || png->height > cMaxPNGSize) { - longjmp(JMPBUF(png), 1); - return; - } - - // We can fill in the size now that the header is available. Avoid memory - // corruption issues by neutering setFailed() during this call; if we don't - // do this, failures will cause |m_reader| to be deleted, and our jmpbuf - // will cease to exist. Note that we'll still properly set the failure flag - // in this case as soon as we longjmp(). - m_doNothingOnFailure = true; - bool result = setSize(width, height); - m_doNothingOnFailure = false; - if (!result) { - longjmp(JMPBUF(png), 1); - return; - } - - int bitDepth, colorType, interlaceType, compressionType, filterType, channels; - png_get_IHDR(png, info, &width, &height, &bitDepth, &colorType, &interlaceType, &compressionType, &filterType); - - if ((colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA) && !m_ignoreGammaAndColorProfile) { - // We currently support color profiles only for RGB and RGBA PNGs. Supporting - // color profiles for gray-scale images is slightly tricky, at least using the - // CoreGraphics ICC library, because we expand gray-scale images to RGB but we - // don't similarly transform the color profile. We'd either need to transform - // the color profile or we'd need to decode into a gray-scale image buffer and - // hand that to CoreGraphics. - m_colorProfile = readColorProfile(png, info); - } - - // The options we set here match what Mozilla does. - - // Expand to ensure we use 24-bit for RGB and 32-bit for RGBA. - if (colorType == PNG_COLOR_TYPE_PALETTE || (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)) - png_set_expand(png); - - png_bytep trns = 0; - int trnsCount = 0; - if (png_get_valid(png, info, PNG_INFO_tRNS)) { - png_get_tRNS(png, info, &trns, &trnsCount, 0); - png_set_expand(png); - } - - if (bitDepth == 16) - png_set_strip_16(png); - - if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); - - // Deal with gamma and keep it under our control. - double gamma; - if (!m_ignoreGammaAndColorProfile && png_get_gAMA(png, info, &gamma)) { - if ((gamma <= 0.0) || (gamma > cMaxGamma)) { - gamma = cInverseGamma; - png_set_gAMA(png, info, gamma); - } - png_set_gamma(png, cDefaultGamma, gamma); - } else - png_set_gamma(png, cDefaultGamma, cInverseGamma); - - // Tell libpng to send us rows for interlaced pngs. - if (interlaceType == PNG_INTERLACE_ADAM7) - png_set_interlace_handling(png); - - // Update our info now. - png_read_update_info(png, info); - channels = png_get_channels(png, info); - ASSERT(channels == 3 || channels == 4); - - m_reader->setHasAlpha(channels == 4); - - if (m_reader->decodingSizeOnly()) { - // If we only needed the size, halt the reader. - m_reader->setReadOffset(m_reader->currentBufferSize() - png->buffer_size); - png->buffer_size = 0; - } -} - -void PNGImageDecoder::rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass) -{ - if (m_frameBufferCache.isEmpty()) - return; - - // Initialize the framebuffer if needed. - RGBA32Buffer& buffer = m_frameBufferCache[0]; - if (buffer.status() == RGBA32Buffer::FrameEmpty) { - if (!buffer.setSize(scaledSize().width(), scaledSize().height())) { - longjmp(JMPBUF(m_reader->pngPtr()), 1); - return; - } - buffer.setStatus(RGBA32Buffer::FramePartial); - buffer.setHasAlpha(false); - buffer.setColorProfile(m_colorProfile); - - // For PNGs, the frame always fills the entire image. - buffer.setRect(IntRect(IntPoint(), size())); - - if (m_reader->pngPtr()->interlaced) - m_reader->createInterlaceBuffer((m_reader->hasAlpha() ? 4 : 3) * size().width() * size().height()); - } - - if (!rowBuffer) - return; - - // libpng comments (pasted in here to explain what follows) - /* - * this function is called for every row in the image. If the - * image is interlacing, and you turned on the interlace handler, - * this function will be called for every row in every pass. - * Some of these rows will not be changed from the previous pass. - * When the row is not changed, the new_row variable will be NULL. - * The rows and passes are called in order, so you don't really - * need the row_num and pass, but I'm supplying them because it - * may make your life easier. - * - * For the non-NULL rows of interlaced images, you must call - * png_progressive_combine_row() passing in the row and the - * old row. You can call this function for NULL rows (it will - * just return) and for non-interlaced images (it just does the - * memcpy for you) if it will make the code easier. Thus, you - * can just do this for all cases: - * - * png_progressive_combine_row(png_ptr, old_row, new_row); - * - * where old_row is what was displayed for previous rows. Note - * that the first pass (pass == 0 really) will completely cover - * the old row, so the rows do not have to be initialized. After - * the first pass (and only for interlaced images), you will have - * to pass the current row, and the function will combine the - * old row and the new row. - */ - - png_structp png = m_reader->pngPtr(); - bool hasAlpha = m_reader->hasAlpha(); - unsigned colorChannels = hasAlpha ? 4 : 3; - png_bytep row; - png_bytep interlaceBuffer = m_reader->interlaceBuffer(); - if (interlaceBuffer) { - row = interlaceBuffer + (rowIndex * colorChannels * size().width()); - png_progressive_combine_row(png, row, rowBuffer); - } else - row = rowBuffer; - - // Copy the data into our buffer. - int width = scaledSize().width(); - int destY = scaledY(rowIndex); - - // Check that the row is within the image bounds. LibPNG may supply an extra row. - if (destY < 0 || destY >= scaledSize().height()) - return; - bool nonTrivialAlpha = false; - for (int x = 0; x < width; ++x) { - png_bytep pixel = row + (m_scaled ? m_scaledColumns[x] : x) * colorChannels; - unsigned alpha = hasAlpha ? pixel[3] : 255; - buffer.setRGBA(x, destY, pixel[0], pixel[1], pixel[2], alpha); - nonTrivialAlpha |= alpha < 255; - } - if (nonTrivialAlpha && !buffer.hasAlpha()) - buffer.setHasAlpha(nonTrivialAlpha); -} - -void PNGImageDecoder::pngComplete() -{ - if (!m_frameBufferCache.isEmpty()) - m_frameBufferCache.first().setStatus(RGBA32Buffer::FrameComplete); -} - -void PNGImageDecoder::decode(bool onlySize) -{ - if (failed()) - return; - - if (!m_reader) - m_reader.set(new PNGImageReader(this)); - - // If we couldn't decode the image but we've received all the data, decoding - // has failed. - if (!m_reader->decode(*m_data, onlySize) && isAllDataReceived()) - setFailed(); - // If we're done decoding the image, we don't need the PNGImageReader - // anymore. (If we failed, |m_reader| has already been cleared.) - else if (isComplete()) - m_reader.clear(); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h deleted file mode 100644 index 1e8902f..0000000 --- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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. - */ - -#ifndef PNGImageDecoder_h -#define PNGImageDecoder_h - -#include "ImageDecoder.h" -#include <wtf/OwnPtr.h> - -namespace WebCore { - - class PNGImageReader; - - // This class decodes the PNG image format. - class PNGImageDecoder : public ImageDecoder { - public: - PNGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - virtual ~PNGImageDecoder(); - - // ImageDecoder - virtual String filenameExtension() const { return "png"; } - virtual bool isSizeAvailable(); - virtual bool setSize(unsigned width, unsigned height); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid - // accessing deleted memory, especially when calling this from inside - // PNGImageReader! - virtual bool setFailed(); - - // Callbacks from libpng - void headerAvailable(); - void rowAvailable(unsigned char* rowBuffer, unsigned rowIndex, int interlacePass); - void pngComplete(); - - bool isComplete() const - { - return !m_frameBufferCache.isEmpty() && (m_frameBufferCache.first().status() == RGBA32Buffer::FrameComplete); - } - - private: - // Decodes the image. If |onlySize| is true, stops decoding after - // calculating the image size. If decoding fails but there is no more - // data coming, sets the "decode failure" flag. - void decode(bool onlySize); - - OwnPtr<PNGImageReader> m_reader; - bool m_doNothingOnFailure; - }; - -} // namespace WebCore - -#endif diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp deleted file mode 100644 index 998234f..0000000 --- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008, 2009 Google, Inc. - * Copyright (C) 2009 Holger Hans Peter Freyther - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" - -#include "NotImplemented.h" - -#include <QPixmap> -#include <stdio.h> - -namespace WebCore { - -RGBA32Buffer::RGBA32Buffer() - : m_hasAlpha(false) - , m_size() - , m_status(FrameEmpty) - , m_duration(0) - , m_disposalMethod(DisposeNotSpecified) -{ -} - -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) -{ - if (this == &other) - return *this; - - copyBitmapData(other); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - return *this; -} - -void RGBA32Buffer::clear() -{ - m_pixmap = QPixmap(); - m_image = QImage(); - m_status = FrameEmpty; - // NOTE: Do not reset other members here; clearFrameBufferCache() - // calls this to free the bitmap data, but other functions like - // initFrameBuffer() and frameComplete() may still need to read - // other metadata out of this frame later. -} - -void RGBA32Buffer::zeroFill() -{ - if (m_pixmap.isNull() && !m_image.isNull()) { - m_pixmap = QPixmap(m_image.width(), m_image.height()); - m_image = QImage(); - } - m_pixmap.fill(QColor(0, 0, 0, 0)); -} - -bool RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) -{ - if (this == &other) - return true; - - m_image = other.m_image; - m_pixmap = other.m_pixmap; - m_size = other.m_size; - m_hasAlpha = other.m_hasAlpha; - return true; -} - -bool RGBA32Buffer::setSize(int newWidth, int newHeight) -{ - // This function should only be called once, it will leak memory - // otherwise. - ASSERT(width() == 0 && height() == 0); - - m_size = IntSize(newWidth, newHeight); - m_image = QImage(); - m_pixmap = QPixmap(newWidth, newHeight); - if (m_pixmap.isNull()) - return false; - - // Zero the image. - zeroFill(); - - return true; -} - -QPixmap* RGBA32Buffer::asNewNativeImage() const -{ - if (m_pixmap.isNull() && !m_image.isNull()) { - m_pixmap = QPixmap::fromImage(m_image); - m_image = QImage(); - } - return new QPixmap(m_pixmap); -} - -bool RGBA32Buffer::hasAlpha() const -{ - return m_hasAlpha; -} - -void RGBA32Buffer::setHasAlpha(bool alpha) -{ - m_hasAlpha = alpha; -} - -void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) -{ - notImplemented(); -} - -void RGBA32Buffer::setStatus(FrameStatus status) -{ - m_status = status; -} - -// The image must not have format 8888 pre multiplied... -void RGBA32Buffer::setPixmap(const QPixmap& pixmap) -{ - m_pixmap = pixmap; - m_image = QImage(); - m_size = pixmap.size(); - m_hasAlpha = pixmap.hasAlphaChannel(); -} - -int RGBA32Buffer::width() const -{ - return m_size.width(); -} - -int RGBA32Buffer::height() const -{ - return m_size.height(); -} - -} diff --git a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp b/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp deleted file mode 100644 index 50e2106..0000000 --- a/WebCore/platform/image-decoders/skia/ImageDecoderSkia.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008, 2009 Google, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" -#if PLATFORM(ANDROID) -#include "SkBitmapRef.h" -#endif - -#include "NotImplemented.h" - -namespace WebCore { - -RGBA32Buffer::RGBA32Buffer() - : m_status(FrameEmpty) - , m_duration(0) - , m_disposalMethod(DisposeNotSpecified) - , m_premultiplyAlpha(true) -{ -} - -RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other) -{ - if (this == &other) - return *this; - - m_bitmap = other.m_bitmap; - // Keep the pixels locked since we will be writing directly into the - // bitmap throughout this object's lifetime. - m_bitmap.lockPixels(); - setRect(other.rect()); - setStatus(other.status()); - setDuration(other.duration()); - setDisposalMethod(other.disposalMethod()); - setPremultiplyAlpha(other.premultiplyAlpha()); - return *this; -} - -void RGBA32Buffer::clear() -{ - m_bitmap.reset(); - m_status = FrameEmpty; - // NOTE: Do not reset other members here; clearFrameBufferCache() - // calls this to free the bitmap data, but other functions like - // initFrameBuffer() and frameComplete() may still need to read - // other metadata out of this frame later. -} - -void RGBA32Buffer::zeroFill() -{ - m_bitmap.eraseARGB(0, 0, 0, 0); -} - -bool RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other) -{ - if (this == &other) - return true; - - m_bitmap.reset(); - const NativeImageSkia& otherBitmap = other.m_bitmap; - return otherBitmap.copyTo(&m_bitmap, otherBitmap.config()); -} - -bool RGBA32Buffer::setSize(int newWidth, int newHeight) -{ - // This function should only be called once, it will leak memory - // otherwise. - ASSERT(width() == 0 && height() == 0); - m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, newWidth, newHeight); - if (!m_bitmap.allocPixels()) - return false; - - // Zero the image. - zeroFill(); - - return true; -} - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ -#if PLATFORM(ANDROID) - return new SkBitmapRef(m_bitmap); -#else - return new NativeImageSkia(m_bitmap); -#endif -} - -bool RGBA32Buffer::hasAlpha() const -{ - return !m_bitmap.isOpaque(); -} - -void RGBA32Buffer::setHasAlpha(bool alpha) -{ - m_bitmap.setIsOpaque(!alpha); -} - -void RGBA32Buffer::setColorProfile(const ColorProfile& colorProfile) -{ - notImplemented(); -} - -void RGBA32Buffer::setStatus(FrameStatus status) -{ - m_status = status; - if (m_status == FrameComplete) - m_bitmap.setDataComplete(); // Tell the bitmap it's done. -} - -int RGBA32Buffer::width() const -{ - return m_bitmap.width(); -} - -int RGBA32Buffer::height() const -{ - return m_bitmap.height(); -} - -} // namespace WebCore diff --git a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp deleted file mode 100644 index a988d9c..0000000 --- a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2010 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: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "WEBPImageDecoder.h" - -#if USE(WEBP) - -#include "webp/decode.h" - -namespace WebCore { - -WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption, - ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption) - : ImageDecoder(alphaOption, gammaAndColorProfileOption) -{ -} - -WEBPImageDecoder::~WEBPImageDecoder() -{ -} - -bool WEBPImageDecoder::isSizeAvailable() -{ - if (!ImageDecoder::isSizeAvailable()) - decode(true); - - return ImageDecoder::isSizeAvailable(); -} - -RGBA32Buffer* WEBPImageDecoder::frameBufferAtIndex(size_t index) -{ - if (index) - return 0; - - if (m_frameBufferCache.isEmpty()) { - m_frameBufferCache.resize(1); - m_frameBufferCache[0].setPremultiplyAlpha(m_premultiplyAlpha); - } - - RGBA32Buffer& frame = m_frameBufferCache[0]; - if (frame.status() != RGBA32Buffer::FrameComplete) - decode(false); - return &frame; -} - - -bool WEBPImageDecoder::decode(bool onlySize) -{ - // Minimum number of bytes needed to ensure one can parse size information. - static const size_t sizeOfHeader = 30; - // Number of bytes per pixel. - static const int bytesPerPixel = 3; - - if (failed()) - return false; - const size_t dataSize = m_data->buffer().size(); - const uint8_t* dataBytes = - reinterpret_cast<const uint8_t*>(m_data->buffer().data()); - int width, height; - if (dataSize < sizeOfHeader) - return true; - if (!WebPGetInfo(dataBytes, dataSize, &width, &height)) - return setFailed(); - if (!ImageDecoder::isSizeAvailable() && !setSize(width, height)) - return setFailed(); - if (onlySize) - return true; - - // FIXME: Add support for progressive decoding. - if (!isAllDataReceived()) - return true; - ASSERT(!m_frameBufferCache.isEmpty()); - RGBA32Buffer& buffer = m_frameBufferCache[0]; - if (buffer.status() == RGBA32Buffer::FrameEmpty) { - ASSERT(width == size().width()); - ASSERT(height == size().height()); - if (!buffer.setSize(width, height)) - return setFailed(); - } - const int stride = width * bytesPerPixel; - Vector<uint8_t> rgb; - rgb.resize(height * stride); - if (!WebPDecodeBGRInto(dataBytes, dataSize, rgb.data(), rgb.size(), stride)) - return setFailed(); - // FIXME: remove this data copy. - for (int y = 0; y < height; ++y) { - const uint8_t* const src = &rgb[y * stride]; - for (int x = 0; x < width; ++x) - buffer.setRGBA(x, y, src[bytesPerPixel * x + 2], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 0], 0xff); - } - buffer.setStatus(RGBA32Buffer::FrameComplete); - buffer.setHasAlpha(false); - buffer.setRect(IntRect(IntPoint(), size())); - return true; -} - -} - -#endif diff --git a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h deleted file mode 100644 index 6cf8870..0000000 --- a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2010 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: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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. - */ - -#ifndef WEBPImageDecoder_h -#define WEBPImageDecoder_h - -#include "ImageDecoder.h" - -#if USE(WEBP) - -namespace WebCore { - -class WEBPImageDecoder : public ImageDecoder { -public: - WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); - virtual ~WEBPImageDecoder(); - virtual String filenameExtension() const { return "vp8"; } - virtual bool isSizeAvailable(); - virtual RGBA32Buffer* frameBufferAtIndex(size_t index); - virtual bool supportsAlpha() const { return false; } - -private: - // Returns false in case of decoding failure. - bool decode(bool onlySize); -}; - -} // namespace WebCore - -#endif - -#endif diff --git a/WebCore/platform/image-decoders/wx/ImageDecoderWx.cpp b/WebCore/platform/image-decoders/wx/ImageDecoderWx.cpp deleted file mode 100644 index 966eb90..0000000 --- a/WebCore/platform/image-decoders/wx/ImageDecoderWx.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, 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: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "ImageDecoder.h" - -// FIXME: Are all these needed? -#include <wx/defs.h> -#include <wx/bitmap.h> -#if USE(WXGC) -#include <wx/graphics.h> -#endif -#include <wx/image.h> -#include <wx/rawbmp.h> - -namespace WebCore { - -NativeImagePtr RGBA32Buffer::asNewNativeImage() const -{ - wxBitmap* bmp = new wxBitmap(width(), height(), 32); - - { - typedef wxPixelData<wxBitmap, wxAlphaPixelFormat> WxPixelData; - WxPixelData data(*bmp); - - // NB: It appears that the data is in BGRA format instead of RGBA format. - // This code works properly on both ppc and intel, meaning the issue is - // likely not an issue of byte order getting mixed up on different archs. - const unsigned char* bytes = (const unsigned char*)m_bytes; - int rowCounter = 0; - long pixelCounter = 0; - WxPixelData::Iterator p(data); - WxPixelData::Iterator rowStart = p; - for (size_t i = 0; i < m_size.width() * m_size.height() * sizeof(PixelData); i += sizeof(PixelData)) { - p.Red() = bytes[i + 2]; - p.Green() = bytes[i + 1]; - p.Blue() = bytes[i + 0]; - p.Alpha() = bytes[i + 3]; - - p++; - - pixelCounter++; - if ((pixelCounter % width()) == 0) { - rowCounter++; - p = rowStart; - p.MoveTo(data, 0, rowCounter); - } - } -#if !wxCHECK_VERSION(2,9,0) - bmp->UseAlpha(); -#endif - } // ensure that WxPixelData is destroyed as it unlocks the bitmap data in - // its dtor and we can't access it (notably in CreateBitmap() below) - // before this is done - - ASSERT(bmp->IsOk()); - -#if USE(WXGC) - wxGraphicsBitmap* bitmap = new wxGraphicsBitmap(wxGraphicsRenderer::GetDefaultRenderer()->CreateBitmap(*bmp)); - delete bmp; - return bitmap; -#else - return bmp; -#endif -} - -} // namespace WebCore |