#ifndef ImageFrame_h
#define ImageFrame_h
#include "platform/PlatformExport.h"
#include "platform/geometry/IntRect.h"
#include "platform/graphics/skia/NativeImageSkia.h"
#include "wtf/Assertions.h"
#include "wtf/PassRefPtr.h"
namespace WebCore {
class PLATFORM_EXPORT ImageFrame {
public:
enum Status { FrameEmpty, FramePartial, FrameComplete };
enum DisposalMethod {
DisposeNotSpecified,
DisposeKeep,
DisposeOverwriteBgcolor,
DisposeOverwritePrevious
};
enum AlphaBlendSource {
BlendAtopPreviousFrame,
BlendAtopBgcolor,
};
typedef uint32_t PixelData;
ImageFrame();
ImageFrame(const ImageFrame& other) { operator=(other); }
ImageFrame& operator=(const ImageFrame& other);
void clearPixelData();
void zeroFillPixelData();
void zeroFillFrameRect(const IntRect&);
bool copyBitmapData(const ImageFrame&);
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);
}
bool setSize(int newWidth, int newHeight);
PassRefPtr<NativeImageSkia> asNewNativeImage() const;
bool hasAlpha() const;
const IntRect& originalFrameRect() const { return m_originalFrameRect; }
Status status() const { return m_status; }
unsigned duration() const { return m_duration; }
DisposalMethod disposalMethod() const { return m_disposalMethod; }
AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; }
bool premultiplyAlpha() const { return m_premultiplyAlpha; }
SkBitmap::Allocator* allocator() const { return m_allocator; }
const SkBitmap& getSkBitmap() const { return m_bitmap; }
bool pixelsChanged() const { return m_pixelsChanged; }
size_t requiredPreviousFrameIndex() const
{
ASSERT(m_requiredPreviousFrameIndexValid);
return m_requiredPreviousFrameIndex;
}
#if !ASSERT_DISABLED
bool requiredPreviousFrameIndexValid() const { return m_requiredPreviousFrameIndexValid; }
#endif
void setHasAlpha(bool alpha);
void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
void setStatus(Status);
void setDuration(unsigned duration) { m_duration = duration; }
void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; }
void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBlendSource = alphaBlendSource; }
void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; }
void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = bitmap; }
void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChanged; }
void setRequiredPreviousFrameIndex(size_t previousFrameIndex)
{
m_requiredPreviousFrameIndex = previousFrameIndex;
#if !ASSERT_DISABLED
m_requiredPreviousFrameIndexValid = true;
#endif
}
inline PixelData* getAddr(int x, int y)
{
return m_bitmap.getAddr32(x, y);
}
inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
{
setRGBA(getAddr(x, y), r, g, b, a);
}
static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1;
inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
if (m_premultiplyAlpha && a < 255) {
if (!a) {
*dest = 0;
return;
}
unsigned alpha = a * div255;
r = (r * alpha) >> 24;
g = (g * alpha) >> 24;
b = (b * alpha) >> 24;
}
*dest = SkPackARGB32NoCheck(a, r, g, b);
}
inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
{
*dest = SkPackARGB32NoCheck(a, r, g, b);
}
inline void notifyBitmapIfPixelsChanged()
{
if (m_pixelsChanged)
m_bitmap.notifyPixelsChanged();
m_pixelsChanged = false;
}
private:
int width() const
{
return m_bitmap.width();
}
int height() const
{
return m_bitmap.height();
}
SkBitmap m_bitmap;
SkBitmap::Allocator* m_allocator;
bool m_hasAlpha;
IntRect m_originalFrameRect;
Status m_status;
unsigned m_duration;
DisposalMethod m_disposalMethod;
AlphaBlendSource m_alphaBlendSource;
bool m_premultiplyAlpha;
bool m_pixelsChanged;
size_t m_requiredPreviousFrameIndex;
#if !ASSERT_DISABLED
bool m_requiredPreviousFrameIndexValid;
#endif
};
}
#endif