• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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