| /* | 
 |  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved. | 
 |  * Copyright (C) Research In Motion Limited 2009-2010. 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 SKY_ENGINE_PLATFORM_IMAGE_DECODERS_IMAGEFRAME_H_ | 
 | #define SKY_ENGINE_PLATFORM_IMAGE_DECODERS_IMAGEFRAME_H_ | 
 |  | 
 | #include "sky/engine/platform/geometry/IntRect.h" | 
 | #include "sky/engine/platform/graphics/skia/NativeImageSkia.h" | 
 | #include "sky/engine/platform/PlatformExport.h" | 
 | #include "sky/engine/wtf/Assertions.h" | 
 | #include "sky/engine/wtf/PassRefPtr.h" | 
 | #include "third_party/skia/include/core/SkColorPriv.h" | 
 |  | 
 | namespace blink { | 
 |  | 
 | // ImageFrame represents the decoded image data.  This buffer is what all | 
 | // decoders write a single frame into. | 
 | class PLATFORM_EXPORT ImageFrame { | 
 | public: | 
 |     enum Status { FrameEmpty, FramePartial, FrameComplete }; | 
 |     enum DisposalMethod { | 
 |         // 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 fully transparent | 
 |         DisposeOverwritePrevious // Clear frame to previous framebuffer contents | 
 |     }; | 
 |     // Indicates how non-opaque pixels in the current frame rectangle | 
 |     // are blended with those in the previous frame. | 
 |     // Notes: | 
 |     // * GIF always uses 'BlendAtopPreviousFrame'. | 
 |     // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for | 
 |     //   cases where one wants to transform a few opaque pixels of the | 
 |     //   previous frame into non-opaque pixels in the current frame. | 
 |     enum AlphaBlendSource { | 
 |         // Blend non-opaque pixels atop the corresponding pixels in the | 
 |         // initial buffer state (i.e. any previous frame buffer after having | 
 |         // been properly disposed). | 
 |         BlendAtopPreviousFrame, | 
 |  | 
 |         // Blend non-opaque pixels against fully transparent (i.e. simply | 
 |         // overwrite the corresponding pixels). | 
 |         BlendAtopBgcolor, | 
 |     }; | 
 |     typedef uint32_t PixelData; | 
 |  | 
 |     ImageFrame(); | 
 |  | 
 |     ImageFrame(const ImageFrame& 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. | 
 |     ImageFrame& operator=(const ImageFrame& other); | 
 |  | 
 |     // These do not touch other metadata, only the raw pixel data. | 
 |     void clearPixelData(); | 
 |     void zeroFillPixelData(); | 
 |     void zeroFillFrameRect(const IntRect&); | 
 |  | 
 |     // Makes this frame have an independent copy of the provided image's | 
 |     // pixel data, so that modifications in one frame are not reflected in | 
 |     // the other.  Returns whether the copy succeeded. | 
 |     bool copyBitmapData(const ImageFrame&); | 
 |  | 
 |     // 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); | 
 |     } | 
 |  | 
 |     // Allocates space for the pixel data.  Must be called before any pixels | 
 |     // are written.  Must only be called once.  Returns whether allocation | 
 |     // succeeded. | 
 |     bool setSize(int newWidth, int newHeight); | 
 |  | 
 |     // Returns a caller-owned pointer to the underlying native image data. | 
 |     // (Actual use: This pointer will be owned by BitmapImage and freed in | 
 |     // FrameData::clear()). | 
 |     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; } | 
 |     // Returns true if the pixels changed, but the bitmap has not yet been notified. | 
 |     bool pixelsChanged() const { return m_pixelsChanged; } | 
 |  | 
 |     size_t requiredPreviousFrameIndex() const | 
 |     { | 
 |         ASSERT(m_requiredPreviousFrameIndexValid); | 
 |         return m_requiredPreviousFrameIndex; | 
 |     } | 
 | #if ENABLE(ASSERT) | 
 |     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; } | 
 |     // The pixelsChanged flag needs to be set when the raw pixel data was directly modified | 
 |     // (e.g. through a pointer or setRGBA). The flag is usually set after a batch of changes was made. | 
 |     void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChanged; } | 
 |  | 
 |     void setRequiredPreviousFrameIndex(size_t previousFrameIndex) | 
 |     { | 
 |         m_requiredPreviousFrameIndex = previousFrameIndex; | 
 | #if ENABLE(ASSERT) | 
 |         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); | 
 |     } | 
 |  | 
 |     inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) | 
 |     { | 
 |         if (m_premultiplyAlpha) | 
 |             setRGBAPremultiply(dest, r, g, b, a); | 
 |         else | 
 |             *dest = SkPackARGB32NoCheck(a, r, g, b); | 
 |     } | 
 |  | 
 |     static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1; | 
 |  | 
 |     static inline void setRGBAPremultiply(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) | 
 |     { | 
 |         if (a < 255) { | 
 |             if (!a) { | 
 |                 *dest = 0; | 
 |                 return; | 
 |             } | 
 |  | 
 |             unsigned alpha = a * div255; | 
 |             r = (r * alpha) >> 24; | 
 |             g = (g * alpha) >> 24; | 
 |             b = (b * alpha) >> 24; | 
 |         } | 
 |  | 
 |         // Call the "NoCheck" version since we may deliberately pass non-premultiplied | 
 |         // values, and we don't want an assert. | 
 |         *dest = SkPackARGB32NoCheck(a, r, g, b); | 
 |     } | 
 |  | 
 |     static inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) | 
 |     { | 
 |         *dest = SkPackARGB32NoCheck(a, r, g, b); | 
 |     } | 
 |  | 
 |     // Notifies the SkBitmap if any pixels changed and resets the flag. | 
 |     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; | 
 |     // This will always just be the entire buffer except for GIF or WebP | 
 |     // frames whose original rect was smaller than the overall image size. | 
 |     IntRect m_originalFrameRect; | 
 |     Status m_status; | 
 |     unsigned m_duration; | 
 |     DisposalMethod m_disposalMethod; | 
 |     AlphaBlendSource m_alphaBlendSource; | 
 |     bool m_premultiplyAlpha; | 
 |     // True if the pixels changed, but the bitmap has not yet been notified. | 
 |     bool m_pixelsChanged; | 
 |  | 
 |     // The frame that must be decoded before this frame can be decoded. | 
 |     // WTF::kNotFound if this frame doesn't require any previous frame. | 
 |     // This is used by ImageDecoder::clearCacheExceptFrame(), and will never | 
 |     // be read for image formats that do not have multiple frames. | 
 |     size_t m_requiredPreviousFrameIndex; | 
 | #if ENABLE(ASSERT) | 
 |     bool m_requiredPreviousFrameIndexValid; | 
 | #endif | 
 | }; | 
 |  | 
 | } // namespace blink | 
 |  | 
 | #endif  // SKY_ENGINE_PLATFORM_IMAGE_DECODERS_IMAGEFRAME_H_ |