1 /* 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 3 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef ImageFrame_h 28 #define ImageFrame_h 29 30 #include "platform/PlatformExport.h" 31 #include "platform/geometry/IntRect.h" 32 #include "platform/graphics/skia/NativeImageSkia.h" 33 #include "wtf/Assertions.h" 34 #include "wtf/PassRefPtr.h" 35 36 namespace WebCore { 37 38 // ImageFrame represents the decoded image data. This buffer is what all 39 // decoders write a single frame into. 40 class PLATFORM_EXPORT ImageFrame { 41 public: 42 enum Status { FrameEmpty, FramePartial, FrameComplete }; 43 enum DisposalMethod { 44 // If you change the numeric values of these, make sure you audit 45 // all users, as some users may cast raw values to/from these 46 // constants. 47 DisposeNotSpecified, // Leave frame in framebuffer 48 DisposeKeep, // Leave frame in framebuffer 49 DisposeOverwriteBgcolor, // Clear frame to fully transparent 50 DisposeOverwritePrevious // Clear frame to previous framebuffer contents 51 }; 52 // Indicates how non-opaque pixels in the current frame rectangle 53 // are blended with those in the previous frame. 54 // Notes: 55 // * GIF always uses 'BlendAtopPreviousFrame'. 56 // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for 57 // cases where one wants to transform a few opaque pixels of the 58 // previous frame into non-opaque pixels in the current frame. 59 enum AlphaBlendSource { 60 // Blend non-opaque pixels atop the corresponding pixels in the 61 // initial buffer state (i.e. any previous frame buffer after having 62 // been properly disposed). 63 BlendAtopPreviousFrame, 64 65 // Blend non-opaque pixels against fully transparent (i.e. simply 66 // overwrite the corresponding pixels). 67 BlendAtopBgcolor, 68 }; 69 typedef uint32_t PixelData; 70 71 ImageFrame(); 72 73 ImageFrame(const ImageFrame& other) { operator=(other); } 74 75 // For backends which refcount their data, this operator doesn't need to 76 // create a new copy of the image data, only increase the ref count. 77 ImageFrame& operator=(const ImageFrame& other); 78 79 // These do not touch other metadata, only the raw pixel data. 80 void clearPixelData(); 81 void zeroFillPixelData(); 82 void zeroFillFrameRect(const IntRect&); 83 84 // Makes this frame have an independent copy of the provided image's 85 // pixel data, so that modifications in one frame are not reflected in 86 // the other. Returns whether the copy succeeded. 87 bool copyBitmapData(const ImageFrame&); 88 89 // Copies the pixel data at [(startX, startY), (endX, startY)) to the 90 // same X-coordinates on each subsequent row up to but not including 91 // endY. 92 void copyRowNTimes(int startX, int endX, int startY, int endY) 93 { 94 ASSERT(startX < width()); 95 ASSERT(endX <= width()); 96 ASSERT(startY < height()); 97 ASSERT(endY <= height()); 98 const int rowBytes = (endX - startX) * sizeof(PixelData); 99 const PixelData* const startAddr = getAddr(startX, startY); 100 for (int destY = startY + 1; destY < endY; ++destY) 101 memcpy(getAddr(startX, destY), startAddr, rowBytes); 102 } 103 104 // Allocates space for the pixel data. Must be called before any pixels 105 // are written. Must only be called once. Returns whether allocation 106 // succeeded. 107 bool setSize(int newWidth, int newHeight); 108 109 // Returns a caller-owned pointer to the underlying native image data. 110 // (Actual use: This pointer will be owned by BitmapImage and freed in 111 // FrameData::clear()). 112 PassRefPtr<NativeImageSkia> asNewNativeImage() const; 113 114 bool hasAlpha() const; 115 const IntRect& originalFrameRect() const { return m_originalFrameRect; } 116 Status status() const { return m_status; } 117 unsigned duration() const { return m_duration; } 118 DisposalMethod disposalMethod() const { return m_disposalMethod; } 119 AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; } 120 bool premultiplyAlpha() const { return m_premultiplyAlpha; } 121 SkBitmap::Allocator* allocator() const { return m_allocator; } 122 const SkBitmap& getSkBitmap() const { return m_bitmap->bitmap(); } 123 // Returns true if the pixels changed, but the bitmap has not yet been notified. 124 bool pixelsChanged() const { return m_pixelsChanged; } 125 126 size_t requiredPreviousFrameIndex() const 127 { 128 ASSERT(m_requiredPreviousFrameIndexValid); 129 return m_requiredPreviousFrameIndex; 130 } 131 #if !ASSERT_DISABLED 132 bool requiredPreviousFrameIndexValid() const { return m_requiredPreviousFrameIndexValid; } 133 #endif 134 void setHasAlpha(bool alpha); 135 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } 136 void setStatus(Status); 137 void setDuration(unsigned duration) { m_duration = duration; } 138 void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod = disposalMethod; } 139 void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBlendSource = alphaBlendSource; } 140 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; } 141 void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator = allocator; } 142 void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = NativeImageSkia::create(bitmap); } 143 // The pixelsChanged flag needs to be set when the raw pixel data was directly modified 144 // (e.g. through a pointer or setRGBA). The flag is usually set after a batch of changes was made. 145 void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChanged; } 146 147 void setRequiredPreviousFrameIndex(size_t previousFrameIndex) 148 { 149 m_requiredPreviousFrameIndex = previousFrameIndex; 150 #if !ASSERT_DISABLED 151 m_requiredPreviousFrameIndexValid = true; 152 #endif 153 } 154 155 inline PixelData* getAddr(int x, int y) 156 { 157 return m_bitmap->bitmap().getAddr32(x, y); 158 } 159 160 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 161 { 162 setRGBA(getAddr(x, y), r, g, b, a); 163 } 164 165 static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 24)) + 1; 166 167 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 168 { 169 if (m_premultiplyAlpha && a < 255) { 170 if (!a) { 171 *dest = 0; 172 return; 173 } 174 175 unsigned alpha = a * div255; 176 r = (r * alpha) >> 24; 177 g = (g * alpha) >> 24; 178 b = (b * alpha) >> 24; 179 } 180 181 // Call the "NoCheck" version since we may deliberately pass non-premultiplied 182 // values, and we don't want an assert. 183 *dest = SkPackARGB32NoCheck(a, r, g, b); 184 } 185 186 inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 187 { 188 *dest = SkPackARGB32NoCheck(a, r, g, b); 189 } 190 191 // Notifies the SkBitmap if any pixels changed and resets the flag. 192 inline void notifyBitmapIfPixelsChanged() 193 { 194 if (m_pixelsChanged) 195 m_bitmap->bitmap().notifyPixelsChanged(); 196 m_pixelsChanged = false; 197 } 198 199 private: 200 int width() const 201 { 202 return m_bitmap->bitmap().width(); 203 } 204 205 int height() const 206 { 207 return m_bitmap->bitmap().height(); 208 } 209 210 RefPtr<NativeImageSkia> m_bitmap; 211 SkBitmap::Allocator* m_allocator; 212 bool m_hasAlpha; 213 // This will always just be the entire buffer except for GIF or WebP 214 // frames whose original rect was smaller than the overall image size. 215 IntRect m_originalFrameRect; 216 Status m_status; 217 unsigned m_duration; 218 DisposalMethod m_disposalMethod; 219 AlphaBlendSource m_alphaBlendSource; 220 bool m_premultiplyAlpha; 221 // True if the pixels changed, but the bitmap has not yet been notified. 222 bool m_pixelsChanged; 223 224 // The frame that must be decoded before this frame can be decoded. 225 // WTF::kNotFound if this frame doesn't require any previous frame. 226 // This is used by ImageDecoder::clearCacheExceptFrame(), and will never 227 // be read for image formats that do not have multiple frames. 228 size_t m_requiredPreviousFrameIndex; 229 #if !ASSERT_DISABLED 230 bool m_requiredPreviousFrameIndexValid; 231 #endif 232 }; 233 234 } // namespace WebCore 235 236 #endif 237