1 /* 2 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef ImageDecoder_h 27 #define ImageDecoder_h 28 29 #include "IntRect.h" 30 #include "ImageSource.h" 31 #include "PlatformString.h" 32 #include "SharedBuffer.h" 33 #include <wtf/Assertions.h> 34 #include <wtf/RefPtr.h> 35 #include <wtf/Vector.h> 36 37 #if (PLATFORM(SKIA) || PLATFORM(SGL)) 38 // TODO(benm): ANDROID: Can we define PLATFORM(SKIA) instead of PLATFORM(SGL) before upstreaming? 39 #include "NativeImageSkia.h" 40 #include "SkBitmap.h" 41 #endif 42 43 namespace WebCore { 44 45 // The RGBA32Buffer object represents the decoded image data in RGBA32 format. This buffer is what all 46 // decoders write a single frame into. Frames are then instantiated for drawing by being handed this buffer. 47 class RGBA32Buffer { 48 public: 49 enum FrameStatus { FrameEmpty, FramePartial, FrameComplete }; 50 enum FrameDisposalMethod { 51 // If you change the numeric values of these, make sure you audit all 52 // users, as some users may cast raw values to/from these constants. 53 DisposeNotSpecified, // Leave frame in framebuffer 54 DisposeKeep, // Leave frame in framebuffer 55 DisposeOverwriteBgcolor, // Clear frame to transparent 56 DisposeOverwritePrevious, // Clear frame to previous framebuffer contents 57 }; 58 #if (PLATFORM(SKIA) || PLATFORM(SGL)) 59 typedef uint32_t PixelData; 60 #else 61 typedef unsigned PixelData; 62 #endif 63 64 RGBA32Buffer(); 65 66 // For backends which refcount their data, this constructor doesn't need 67 // to create a new copy of the image data, only increase the ref count. 68 // 69 // This exists because ImageDecoder keeps a Vector<RGBA32Buffer>, and 70 // Vector requires this constructor. RGBA32Buffer(const RGBA32Buffer & other)71 RGBA32Buffer(const RGBA32Buffer& other) 72 { 73 operator=(other); 74 } 75 76 // Deletes the pixel data entirely; used by ImageDecoder to save memory 77 // when we no longer need to display a frame and only need its metadata. 78 void clear(); 79 80 // Zeroes the pixel data in the buffer, setting it to fully-transparent. 81 void zeroFill(); 82 83 // Creates a new copy of the image data in |other|, so the two images 84 // can be modified independently. 85 void copyBitmapData(const RGBA32Buffer& other); 86 87 // Copies the pixel data at [(startX, startY), (endX, startY)) to the 88 // same X-coordinates on each subsequent row up to but not including 89 // endY. copyRowNTimes(int startX,int endX,int startY,int endY)90 void copyRowNTimes(int startX, int endX, int startY, int endY) 91 { 92 ASSERT(startX < width()); 93 ASSERT(endX <= width()); 94 ASSERT(startY < height()); 95 ASSERT(endY <= height()); 96 const int rowBytes = (endX - startX) * sizeof(PixelData); 97 const PixelData* const startAddr = getAddr(startX, startY); 98 for (int destY = startY + 1; destY < endY; ++destY) 99 memcpy(getAddr(startX, destY), startAddr, rowBytes); 100 } 101 102 #if (PLATFORM(SKIA) || PLATFORM(SGL)) bitmap()103 NativeImageSkia& bitmap() { return m_bitmap; } bitmap()104 const NativeImageSkia& bitmap() const { return m_bitmap; } 105 #endif 106 107 // Allocates space for the pixel data. Must be called before any pixels 108 // are written. Will return true on success, false if the memory 109 // allocation fails. Calling this multiple times is undefined and may 110 // leak memory. 111 bool setSize(int newWidth, int newHeight); 112 113 // To be used by ImageSource::createFrameAtIndex(). Returns a pointer 114 // to the underlying native image data. This pointer will be owned by 115 // the BitmapImage and freed in FrameData::clear(). 116 NativeImagePtr asNewNativeImage() const; 117 118 bool hasAlpha() const; rect()119 const IntRect& rect() const { return m_rect; } status()120 FrameStatus status() const { return m_status; } duration()121 unsigned duration() const { return m_duration; } disposalMethod()122 FrameDisposalMethod disposalMethod() const { return m_disposalMethod; } 123 124 void setHasAlpha(bool alpha); setRect(const IntRect & r)125 void setRect(const IntRect& r) { m_rect = r; } 126 void setStatus(FrameStatus status); setDuration(unsigned duration)127 void setDuration(unsigned duration) { m_duration = duration; } setDisposalMethod(FrameDisposalMethod method)128 void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; } 129 setRGBA(int x,int y,unsigned r,unsigned g,unsigned b,unsigned a)130 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a) 131 { 132 setRGBA(getAddr(x, y), r, g, b, a); 133 } 134 135 private: 136 RGBA32Buffer& operator=(const RGBA32Buffer& other); 137 138 int width() const; 139 int height() const; 140 getAddr(int x,int y)141 inline PixelData* getAddr(int x, int y) 142 { 143 #if PLATFORM(CAIRO) || PLATFORM(WX) 144 return m_bytes.data() + (y * width()) + x; 145 #elif (PLATFORM(SKIA) || PLATFORM(SGL)) 146 return m_bitmap.getAddr32(x, y); 147 #else 148 ASSERT_NOT_REACHED(); 149 return 0; 150 #endif 151 } 152 setRGBA(PixelData * dest,unsigned r,unsigned g,unsigned b,unsigned a)153 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a) 154 { 155 // We store this data pre-multiplied. 156 if (a == 0) 157 *dest = 0; 158 else { 159 if (a < 255) { 160 float alphaPercent = a / 255.0f; 161 r = static_cast<unsigned>(r * alphaPercent); 162 g = static_cast<unsigned>(g * alphaPercent); 163 b = static_cast<unsigned>(b * alphaPercent); 164 } 165 *dest = (a << 24 | r << 16 | g << 8 | b); 166 } 167 } 168 169 #if PLATFORM(CAIRO) || PLATFORM(WX) 170 Vector<PixelData> m_bytes; 171 IntSize m_size; // The size of the buffer. This should be the 172 // same as ImageDecoder::m_size. 173 bool m_hasAlpha; // Whether or not any of the pixels in the buffer have transparency. 174 #elif (PLATFORM(SKIA) || PLATFORM(SGL)) 175 NativeImageSkia m_bitmap; 176 #endif 177 IntRect m_rect; // The rect of the original specified frame within the overall buffer. 178 // This will always just be the entire buffer except for GIF frames 179 // whose original rect was smaller than the overall image size. 180 FrameStatus m_status; // Whether or not this frame is completely finished decoding. 181 unsigned m_duration; // The animation delay. 182 FrameDisposalMethod m_disposalMethod; 183 // What to do with this frame's data when initializing the next frame. 184 }; 185 186 // The ImageDecoder class represents a base class for specific image format decoders 187 // (e.g., GIF, JPG, PNG, ICO) to derive from. All decoders decode into RGBA32 format 188 // and the base class manages the RGBA32 frame cache. 189 class ImageDecoder { 190 public: ImageDecoder()191 ImageDecoder() 192 : m_failed(false) 193 , m_sizeAvailable(false) 194 { 195 } 196 ~ImageDecoder()197 virtual ~ImageDecoder() {} 198 199 // The the filename extension usually associated with an undecoded image of this type. 200 virtual String filenameExtension() const = 0; 201 202 // All specific decoder plugins must do something with the data they are given. setData(SharedBuffer * data,bool allDataReceived)203 virtual void setData(SharedBuffer* data, bool allDataReceived) { m_data = data; } 204 205 // Whether or not the size information has been decoded yet. This default 206 // implementation just returns true if the size has been set and we have not 207 // seen a failure. Decoders may want to override this to lazily decode 208 // enough of the image to get the size. isSizeAvailable()209 virtual bool isSizeAvailable() 210 { 211 return !m_failed && m_sizeAvailable; 212 } 213 214 // Returns the size of the image. size()215 virtual IntSize size() const 216 { 217 // Requesting the size of an invalid bitmap is meaningless. 218 ASSERT(!m_failed); 219 return m_size; 220 } 221 222 // Returns the size of frame |index|. This will only differ from size() 223 // for formats where different frames are different sizes (namely ICO, 224 // where each frame represents a different icon within the master file). 225 // Notably, this does not return different sizes for different GIF 226 // frames, since while these may be stored as smaller rectangles, during 227 // decoding they are composited to create a full-size frame. frameSizeAtIndex(size_t)228 virtual IntSize frameSizeAtIndex(size_t) const 229 { 230 return size(); 231 } 232 233 // Called by the image decoders to set their decoded size, this also check 234 // the size for validity. It will return true if the size was set, or false 235 // if there is an error. On error, the m_failed flag will be set and the 236 // caller should immediately stop decoding. setSize(unsigned width,unsigned height)237 virtual bool setSize(unsigned width, unsigned height) 238 { 239 if (isOverSize(width, height)) { 240 m_failed = true; 241 return false; 242 } 243 m_size = IntSize(width, height); 244 m_sizeAvailable = true; 245 return true; 246 } 247 248 // The total number of frames for the image. Classes that support multiple frames 249 // will scan the image data for the answer if they need to (without necessarily 250 // decoding all of the individual frames). frameCount()251 virtual size_t frameCount() { return 1; } 252 253 // The number of repetitions to perform for an animation loop. repetitionCount()254 virtual int repetitionCount() const { return cAnimationNone; } 255 256 // Called to obtain the RGBA32Buffer full of decoded data for rendering. The 257 // decoder plugin will decode as much of the frame as it can before handing 258 // back the buffer. 259 virtual RGBA32Buffer* frameBufferAtIndex(size_t) = 0; 260 261 // Whether or not the underlying image format even supports alpha transparency. supportsAlpha()262 virtual bool supportsAlpha() const { return true; } 263 failed()264 bool failed() const { return m_failed; } setFailed()265 void setFailed() { m_failed = true; } 266 267 // Wipe out frames in the frame buffer cache before |clearBeforeFrame|, 268 // assuming this can be done without breaking decoding. Different decoders 269 // place different restrictions on what frames are safe to destroy, so this 270 // is left to them to implement. 271 // For convenience's sake, we provide a default (empty) implementation, 272 // since in practice only GIFs will ever use this. clearFrameBufferCache(size_t clearBeforeFrame)273 virtual void clearFrameBufferCache(size_t clearBeforeFrame) { } 274 275 protected: 276 RefPtr<SharedBuffer> m_data; // The encoded data. 277 Vector<RGBA32Buffer> m_frameBufferCache; 278 bool m_failed; 279 280 private: 281 // Some code paths compute the size of the image as "width * height * 4" 282 // and return it as a (signed) int. Avoid overflow. isOverSize(unsigned width,unsigned height)283 static bool isOverSize(unsigned width, unsigned height) 284 { 285 // width * height must not exceed (2 ^ 29) - 1, so that we don't 286 // overflow when we multiply by 4. 287 unsigned long long total_size = static_cast<unsigned long long>(width) 288 * static_cast<unsigned long long>(height); 289 return total_size > ((1 << 29) - 1); 290 } 291 292 IntSize m_size; 293 bool m_sizeAvailable; 294 }; 295 296 } // namespace WebCore 297 298 #endif 299