Commit 0da40070 authored by pkasting@chromium.org's avatar pkasting@chromium.org

2009-06-13 Peter Kasting <pkasting@google.com>

        Reviewed by Eric Seidel.

        https://bugs.webkit.org/show_bug.cgi?id=25709 part ten
        Make Skia use the root directory ImageDecoder.h and factor out most
        Skia-specific bits into skia/ImageDecoderSkia.cpp.  Also fix a pair of
        style violations in ImageDecoderCairo.cpp.  This is the last patch for
        this bug, everything beyond this is an enhancement rather than
        unforking.

        * platform/image-decoders/ImageDecoder.h:
        (WebCore::RGBA32Buffer::getAddr):
        * platform/image-decoders/cairo/ImageDecoderCairo.cpp:
        (WebCore::RGBA32Buffer::hasAlpha):
        (WebCore::RGBA32Buffer::setHasAlpha):
        (WebCore::setStatus):
        * platform/image-decoders/skia/ImageDecoder.h: Removed.
        * platform/image-decoders/skia/ImageDecoderSkia.cpp: Added.
        (WebCore::RGBA32Buffer::RGBA32Buffer):
        (WebCore::RGBA32Buffer::clear):
        (WebCore::RGBA32Buffer::zeroFill):
        (WebCore::RGBA32Buffer::copyBitmapData):
        (WebCore::RGBA32Buffer::setSize):
        (WebCore::RGBA32Buffer::asNewNativeImage):
        (WebCore::RGBA32Buffer::hasAlpha):
        (WebCore::RGBA32Buffer::setHasAlpha):
        (WebCore::RGBA32Buffer::setStatus):
        (WebCore::RGBA32Buffer::operator=):
        (WebCore::RGBA32Buffer::width):
        (WebCore::RGBA32Buffer::height):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@44661 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7663b418
2009-06-13 Peter Kasting <pkasting@google.com>
Reviewed by Eric Seidel.
https://bugs.webkit.org/show_bug.cgi?id=25709 part ten
Make Skia use the root directory ImageDecoder.h and factor out most
Skia-specific bits into skia/ImageDecoderSkia.cpp. Also fix a pair of
style violations in ImageDecoderCairo.cpp. This is the last patch for
this bug, everything beyond this is an enhancement rather than
unforking.
* platform/image-decoders/ImageDecoder.h:
(WebCore::RGBA32Buffer::getAddr):
* platform/image-decoders/cairo/ImageDecoderCairo.cpp:
(WebCore::RGBA32Buffer::hasAlpha):
(WebCore::RGBA32Buffer::setHasAlpha):
(WebCore::setStatus):
* platform/image-decoders/skia/ImageDecoder.h: Removed.
* platform/image-decoders/skia/ImageDecoderSkia.cpp: Added.
(WebCore::RGBA32Buffer::RGBA32Buffer):
(WebCore::RGBA32Buffer::clear):
(WebCore::RGBA32Buffer::zeroFill):
(WebCore::RGBA32Buffer::copyBitmapData):
(WebCore::RGBA32Buffer::setSize):
(WebCore::RGBA32Buffer::asNewNativeImage):
(WebCore::RGBA32Buffer::hasAlpha):
(WebCore::RGBA32Buffer::setHasAlpha):
(WebCore::RGBA32Buffer::setStatus):
(WebCore::RGBA32Buffer::operator=):
(WebCore::RGBA32Buffer::width):
(WebCore::RGBA32Buffer::height):
2009-06-13 Victor Wang <victorw@chromium.org>
Reviewed by Eric Seidel. Landed by Adam Barth.
......@@ -34,6 +34,11 @@
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "SkBitmap.h"
#endif
namespace WebCore {
// The RGBA32Buffer object represents the decoded image data in RGBA32 format. This buffer is what all
......@@ -49,7 +54,11 @@ namespace WebCore {
DisposeOverwriteBgcolor, // Clear frame to transparent
DisposeOverwritePrevious, // Clear frame to previous framebuffer contents
};
#if PLATFORM(SKIA)
typedef uint32_t PixelData;
#else
typedef unsigned PixelData;
#endif
RGBA32Buffer();
......@@ -93,7 +102,7 @@ namespace WebCore {
// 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 width, int height);
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
......@@ -108,7 +117,7 @@ namespace WebCore {
void setHasAlpha(bool alpha);
void setRect(const IntRect& r) { m_rect = r; }
void setStatus(FrameStatus s) { m_status = s; }
void setStatus(FrameStatus status);
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
......@@ -127,6 +136,8 @@ namespace WebCore {
{
#if PLATFORM(CAIRO)
return m_bytes.data() + (y * width()) + x;
#elif PLATFORM(SKIA)
return m_bitmap.getAddr32(x, y);
#endif
}
......@@ -151,6 +162,8 @@ namespace WebCore {
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.
#elif PLATFORM(SKIA)
NativeImageSkia m_bitmap;
#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
......
......@@ -63,12 +63,12 @@ void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other)
setHasAlpha(other.m_hasAlpha);
}
bool RGBA32Buffer::setSize(int width, int height)
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_bytes.resize(width * height);
m_size = IntSize(width, height);
m_bytes.resize(newWidth * newHeight);
m_size = IntSize(newWidth, newHeight);
// Zero the image.
zeroFill();
......@@ -84,14 +84,21 @@ NativeImagePtr RGBA32Buffer::asNewNativeImage() const
width() * sizeof(PixelData));
}
bool RGBA32Buffer::hasAlpha() const {
bool RGBA32Buffer::hasAlpha() const
{
return m_hasAlpha;
}
void RGBA32Buffer::setHasAlpha(bool alpha) {
void RGBA32Buffer::setHasAlpha(bool alpha)
{
m_hasAlpha = alpha;
}
void setStatus(FrameStatus status)
{
m_status = status;
}
RGBA32Buffer& RGBA32Buffer::operator=(const RGBA32Buffer& other)
{
if (this == &other)
......
/*
* 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.
*/
#ifndef ImageDecoder_h
#define ImageDecoder_h
#include "IntRect.h"
#include "ImageSource.h"
#include "NativeImageSkia.h"
#include "PlatformString.h"
#include "SharedBuffer.h"
#include <wtf/Assertions.h>
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
#include "SkBitmap.h"
namespace WebCore {
// 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
};
typedef uint32_t PixelData;
RGBA32Buffer()
: m_status(FrameEmpty)
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
{
}
// This constructor doesn't create a new copy of the image data, it only
// increases the ref count of the existing bitmap.
//
// This exists because ImageDecoder keeps a Vector<RGBA32Buffer>, and
// Vector requires this constructor.
RGBA32Buffer(const RGBA32Buffer& other)
{
operator=(other);
}
void 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 zeroFill()
{
m_bitmap.eraseARGB(0, 0, 0, 0);
}
// This function creates a new copy of the image data in |other|, so the
// two images can be modified independently.
void copyBitmapData(const RGBA32Buffer& other)
{
if (this == &other)
return;
m_bitmap.reset();
const NativeImageSkia& otherBitmap = other.m_bitmap;
otherBitmap.copyTo(&m_bitmap, otherBitmap.config());
}
// This function copies [(startX, startY), (endX, startY)) to the same
// X-coordinates on each subsequent row up to but not including endY.
//
// NOTE: This function does not sanity-check its arguments! Callers
// MUST not pass invalid values or this will corrupt memory.
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);
}
// Must be called before any pixels are written. Will return true on
// success, false if the memory allocation fails.
bool setSize(int new_width, int new_height)
{
// This function should only be called once, it will leak memory
// otherwise.
ASSERT(width() == 0 && height() == 0);
m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, new_width, new_height);
if (!m_bitmap.allocPixels()) {
// Allocation failure, maybe the bitmap was too big.
setStatus(FrameComplete);
return false;
}
// Zero the image.
zeroFill();
return true;
}
// 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
{
return new NativeImageSkia(m_bitmap);
}
bool hasAlpha() const { return !m_bitmap.isOpaque(); }
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; }
void setHasAlpha(bool alpha) { m_bitmap.setIsOpaque(!alpha); }
void setRect(const IntRect& r) { m_rect = r; }
void setStatus(FrameStatus s)
{
m_status = s;
if (s == FrameComplete)
m_bitmap.setDataComplete(); // Tell the bitmap it's done.
}
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
{
setRGBA(getAddr(x, y), r, g, b, a);
}
private:
// Initialize with another buffer. This function doesn't create a new copy
// of the image data, it only increases the refcount of the existing bitmap.
//
// Normal callers should not generally be using this function. If you want
// to create a copy on which you can modify the image data independently,
// use copyBitmapData() instead.
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());
return *this;
}
inline int width() const { return m_bitmap.width(); }
inline int height() const { return m_bitmap.height(); }
inline PixelData* getAddr(int x, int y)
{
return m_bitmap.getAddr32(x, y);
}
inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
// We store this data pre-multiplied.
if (a == 0)
*dest = 0;
else {
if (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);
}
*dest = (a << 24 | r << 16 | g << 8 | b);
}
}
NativeImageSkia m_bitmap;
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.
};
// 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.
class ImageDecoder {
public:
ImageDecoder()
: m_failed(false)
, m_sizeAvailable(false)
{
}
virtual ~ImageDecoder() {}
// The the filename extension usually associated with an undecoded image of this type.
virtual String filenameExtension() const = 0;
// All specific decoder plugins must do something with the data they are given.
virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; }
// 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() const
{
return !m_failed && m_sizeAvailable;
}
// Requests the size.
virtual IntSize size() const
{
// Requesting the size of an invalid bitmap is meaningless.
ASSERT(!m_failed);
return m_size;
}
// 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 int 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 index) = 0;
// Whether or not the underlying image format even supports alpha transparency.
virtual bool supportsAlpha() const { return true; }
bool failed() const { return m_failed; }
void setFailed() { m_failed = true; }
// 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) { }
protected:
// Called by the image decoders to set their decoded size, this also check
// 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.
bool setSize(unsigned width, unsigned height)
{
if (isOverSize(width, height)) {
m_failed = true;
return false;
}
m_size = IntSize(width, height);
m_sizeAvailable = true;
return true;
}
RefPtr<SharedBuffer> m_data; // The encoded data.
Vector<RGBA32Buffer> m_frameBufferCache;
mutable bool m_failed;
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;
};
} // namespace WebCore
#endif
/*
* 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"
namespace WebCore {
RGBA32Buffer::RGBA32Buffer()
: m_status(FrameEmpty)
, m_duration(0)
, m_disposalMethod(DisposeNotSpecified)
{
}
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);
}
void RGBA32Buffer::copyBitmapData(const RGBA32Buffer& other)
{
if (this == &other)
return;
m_bitmap.reset();
const NativeImageSkia& otherBitmap = other.m_bitmap;
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()) {
// Allocation failure, maybe the bitmap was too big.
setStatus(FrameComplete);
return false;
}
// Zero the image.
zeroFill();
return true;
}
NativeImagePtr RGBA32Buffer::asNewNativeImage() const
{
return new NativeImageSkia(m_bitmap);
}
bool RGBA32Buffer::hasAlpha() const
{
return !m_bitmap.isOpaque();
}
void RGBA32Buffer::setHasAlpha(bool alpha)
{
m_bitmap.setIsOpaque(!alpha);
}
void RGBA32Buffer::setStatus(FrameStatus status)
{
m_status = status;
if (m_status == FrameComplete)
m_bitmap.setDataComplete(); // Tell the bitmap it's done.
}
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());
return *this;
}
int RGBA32Buffer::width() const
{
return m_bitmap.width();
}
int RGBA32Buffer::height() const
{
return m_bitmap.height();
}
} // namespace WebCore
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment