Remove the remaining Skia #ifdefs
[WebKit-https.git] / Source / WebCore / platform / image-decoders / ImageDecoder.h
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2008-2009 Torch Mobile, Inc.
4  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
5  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #ifndef ImageDecoder_h
30 #define ImageDecoder_h
31
32 #include "IntRect.h"
33 #include "ImageSource.h"
34 #include "PlatformScreen.h"
35 #include "SharedBuffer.h"
36 #include <wtf/Assertions.h>
37 #include <wtf/RefPtr.h>
38 #include <wtf/Vector.h>
39 #include <wtf/text/WTFString.h>
40
41 #if USE(QCMSLIB)
42 #include "qcms.h"
43 #if OS(DARWIN)
44 #include "GraphicsContextCG.h"
45 #include <ApplicationServices/ApplicationServices.h>
46 #include <wtf/RetainPtr.h>
47 #endif
48 #endif
49
50 namespace WebCore {
51
52     // ImageFrame represents the decoded image data.  This buffer is what all
53     // decoders write a single frame into.
54     class ImageFrame {
55     public:
56         enum FrameStatus { FrameEmpty, FramePartial, FrameComplete };
57         enum FrameDisposalMethod {
58             // If you change the numeric values of these, make sure you audit
59             // all users, as some users may cast raw values to/from these
60             // constants.
61             DisposeNotSpecified,      // Leave frame in framebuffer
62             DisposeKeep,              // Leave frame in framebuffer
63             DisposeOverwriteBgcolor,  // Clear frame to transparent
64             DisposeOverwritePrevious  // Clear frame to previous framebuffer
65                                       // contents
66         };
67         typedef unsigned PixelData;
68
69         ImageFrame();
70
71         ImageFrame(const ImageFrame& other) { operator=(other); }
72
73         // For backends which refcount their data, this operator doesn't need to
74         // create a new copy of the image data, only increase the ref count.
75         ImageFrame& operator=(const ImageFrame& other);
76
77         // These do not touch other metadata, only the raw pixel data.
78         void clearPixelData();
79         void zeroFillPixelData();
80
81         // Makes this frame have an independent copy of the provided image's
82         // pixel data, so that modifications in one frame are not reflected in
83         // the other.  Returns whether the copy succeeded.
84         bool copyBitmapData(const ImageFrame&);
85
86         // Copies the pixel data at [(startX, startY), (endX, startY)) to the
87         // same X-coordinates on each subsequent row up to but not including
88         // endY.
89         void copyRowNTimes(int startX, int endX, int startY, int endY)
90         {
91             ASSERT(startX < width());
92             ASSERT(endX <= width());
93             ASSERT(startY < height());
94             ASSERT(endY <= height());
95             const int rowBytes = (endX - startX) * sizeof(PixelData);
96             const PixelData* const startAddr = getAddr(startX, startY);
97             for (int destY = startY + 1; destY < endY; ++destY)
98                 memcpy(getAddr(startX, destY), startAddr, rowBytes);
99         }
100
101         // Allocates space for the pixel data.  Must be called before any pixels
102         // are written.  Must only be called once.  Returns whether allocation
103         // succeeded.
104         bool setSize(int newWidth, int newHeight);
105
106         // Returns a caller-owned pointer to the underlying native image data.
107         // (Actual use: This pointer will be owned by BitmapImage and freed in
108         // FrameData::clear()).
109         PassNativeImagePtr asNewNativeImage() const;
110
111         bool hasAlpha() const;
112         const IntRect& originalFrameRect() const { return m_originalFrameRect; }
113         FrameStatus status() const { return m_status; }
114         unsigned duration() const { return m_duration; }
115         FrameDisposalMethod disposalMethod() const { return m_disposalMethod; }
116         bool premultiplyAlpha() const { return m_premultiplyAlpha; }
117
118         void setHasAlpha(bool alpha);
119         void setColorProfile(const ColorProfile&);
120         void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; }
121         void setStatus(FrameStatus status);
122         void setDuration(unsigned duration) { m_duration = duration; }
123         void setDisposalMethod(FrameDisposalMethod method) { m_disposalMethod = method; }
124         void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = premultiplyAlpha; }
125
126         inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, unsigned a)
127         {
128             setRGBA(getAddr(x, y), r, g, b, a);
129         }
130
131         inline PixelData* getAddr(int x, int y)
132         {
133             return m_bytes + (y * width()) + x;
134         }
135
136         // Use fix point multiplier instead of integer division or floating point math.
137         // This multipler produces exactly the same result for all values in range 0 - 255.
138         static const unsigned fixPointShift = 24;
139         static const unsigned fixPointMult = static_cast<unsigned>(1.0 / 255.0 * (1 << fixPointShift)) + 1;
140         // Multiplies unsigned value by fixpoint value and converts back to unsigned.
141         static unsigned fixPointUnsignedMultiply(unsigned fixed, unsigned v)
142         {
143             return  (fixed * v) >> fixPointShift;
144         }
145
146         inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b, unsigned a)
147         {
148             if (m_premultiplyAlpha && a < 255) {
149                 if (!a) {
150                     *dest = 0;
151                     return;
152                 }
153
154                 unsigned alphaMult = a * fixPointMult;
155                 r = fixPointUnsignedMultiply(r, alphaMult);
156                 g = fixPointUnsignedMultiply(g, alphaMult);
157                 b = fixPointUnsignedMultiply(b, alphaMult);
158             }
159             *dest = (a << 24 | r << 16 | g << 8 | b);
160         }
161
162     private:
163         int width() const
164         {
165             return m_size.width();
166         }
167
168         int height() const
169         {
170             return m_size.height();
171         }
172
173         Vector<PixelData> m_backingStore;
174         PixelData* m_bytes; // The memory is backed by m_backingStore.
175         IntSize m_size;
176         // FIXME: Do we need m_colorProfile anymore?
177         ColorProfile m_colorProfile;
178         bool m_hasAlpha;
179         IntRect m_originalFrameRect; // This will always just be the entire
180                                      // buffer except for GIF frames whose
181                                      // original rect was smaller than the
182                                      // overall image size.
183         FrameStatus m_status;
184         unsigned m_duration;
185         FrameDisposalMethod m_disposalMethod;
186         bool m_premultiplyAlpha;
187     };
188
189     // ImageDecoder is a base for all format-specific decoders
190     // (e.g. JPEGImageDecoder).  This base manages the ImageFrame cache.
191     //
192     // ENABLE(IMAGE_DECODER_DOWN_SAMPLING) allows image decoders to downsample
193     // at decode time.  Image decoders will downsample any images larger than
194     // |m_maxNumPixels|.  FIXME: Not yet supported by all decoders.
195     class ImageDecoder {
196         WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED;
197     public:
198         ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
199             : m_scaled(false)
200             , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
201             , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
202             , m_sizeAvailable(false)
203             , m_maxNumPixels(-1)
204             , m_isAllDataReceived(false)
205             , m_failed(false) { }
206
207         virtual ~ImageDecoder() { }
208
209         // Returns a caller-owned decoder of the appropriate type.  Returns 0 if
210         // we can't sniff a supported type from the provided data (possibly
211         // because there isn't enough data yet).
212         static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
213
214         virtual String filenameExtension() const = 0;
215
216         bool isAllDataReceived() const { return m_isAllDataReceived; }
217
218         virtual void setData(SharedBuffer* data, bool allDataReceived)
219         {
220             if (m_failed)
221                 return;
222             m_data = data;
223             m_isAllDataReceived = allDataReceived;
224         }
225
226         // Lazily-decodes enough of the image to get the size (if possible).
227         // FIXME: Right now that has to be done by each subclass; factor the
228         // decode call out and use it here.
229         virtual bool isSizeAvailable()
230         {
231             return !m_failed && m_sizeAvailable;
232         }
233
234         virtual IntSize size() const { return m_size; }
235
236         IntSize scaledSize() const
237         {
238             return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : size();
239         }
240
241         // This will only differ from size() for ICO (where each frame is a
242         // different icon) or other formats where different frames are different
243         // sizes.  This does NOT differ from size() for GIF, since decoding GIFs
244         // composites any smaller frames against previous frames to create full-
245         // size frames.
246         virtual IntSize frameSizeAtIndex(size_t) const
247         {
248             return size();
249         }
250
251         // Returns whether the size is legal (i.e. not going to result in
252         // overflow elsewhere).  If not, marks decoding as failed.
253         virtual bool setSize(unsigned width, unsigned height)
254         {
255             if (isOverSize(width, height))
256                 return setFailed();
257             m_size = IntSize(width, height);
258             m_sizeAvailable = true;
259             return true;
260         }
261
262         // Lazily-decodes enough of the image to get the frame count (if
263         // possible), without decoding the individual frames.
264         // FIXME: Right now that has to be done by each subclass; factor the
265         // decode call out and use it here.
266         virtual size_t frameCount() { return 1; }
267
268         virtual int repetitionCount() const { return cAnimationNone; }
269
270         // Decodes as much of the requested frame as possible, and returns an
271         // ImageDecoder-owned pointer.
272         virtual ImageFrame* frameBufferAtIndex(size_t) = 0;
273
274         // Make the best effort guess to check if the requested frame has alpha channel.
275         virtual bool frameHasAlphaAtIndex(size_t) const;
276
277         // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
278         virtual unsigned frameBytesAtIndex(size_t) const;
279
280         void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorProfile = flag; }
281         bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorProfile; }
282
283         ImageOrientation orientation() const { return m_orientation; }
284
285         enum { iccColorProfileHeaderLength = 128 };
286
287         static bool rgbColorProfile(const char* profileData, unsigned profileLength)
288         {
289             ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
290
291             return !memcmp(&profileData[16], "RGB ", 4);
292         }
293
294         static bool inputDeviceColorProfile(const char* profileData, unsigned profileLength)
295         {
296             ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderLength);
297
298             return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[12], "scnr", 4);
299         }
300
301 #if USE(QCMSLIB)
302         static qcms_profile* qcmsOutputDeviceProfile()
303         {
304             static qcms_profile* outputDeviceProfile = 0;
305
306             static bool qcmsInitialized = false;
307             if (!qcmsInitialized) {
308                 qcmsInitialized = true;
309                 // FIXME: Add optional ICCv4 support.
310 #if OS(DARWIN)
311                 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayCopyColorSpace(CGMainDisplayID()));
312                 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpace.get()));
313                 if (iccProfile) {
314                     size_t length = CFDataGetLength(iccProfile);
315                     const unsigned char* systemProfile = CFDataGetBytePtr(iccProfile);
316                     outputDeviceProfile = qcms_profile_from_memory(systemProfile, length);
317                 }
318 #else
319                 // FIXME: add support for multiple monitors.
320                 ColorProfile profile;
321                 screenColorProfile(profile);
322                 if (!profile.isEmpty())
323                     outputDeviceProfile = qcms_profile_from_memory(profile.data(), profile.size());
324 #endif
325                 if (outputDeviceProfile && qcms_profile_is_bogus(outputDeviceProfile)) {
326                     qcms_profile_release(outputDeviceProfile);
327                     outputDeviceProfile = 0;
328                 }
329                 if (!outputDeviceProfile)
330                     outputDeviceProfile = qcms_profile_sRGB();
331                 if (outputDeviceProfile)
332                     qcms_profile_precache_output_transform(outputDeviceProfile);
333             }
334             return outputDeviceProfile;
335         }
336 #endif
337
338         // Sets the "decode failure" flag.  For caller convenience (since so
339         // many callers want to return false after calling this), returns false
340         // to enable easy tailcalling.  Subclasses may override this to also
341         // clean up any local data.
342         virtual bool setFailed()
343         {
344             m_failed = true;
345             return false;
346         }
347
348         bool failed() const { return m_failed; }
349
350         // Clears decoded pixel data from before the provided frame unless that
351         // data may be needed to decode future frames (e.g. due to GIF frame
352         // compositing).
353         virtual void clearFrameBufferCache(size_t) { }
354
355 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
356         void setMaxNumPixels(int m) { m_maxNumPixels = m; }
357 #endif
358
359         // If the image has a cursor hot-spot, stores it in the argument
360         // and returns true. Otherwise returns false.
361         virtual bool hotSpot(IntPoint&) const { return false; }
362
363     protected:
364         void prepareScaleDataIfNecessary();
365         int upperBoundScaledX(int origX, int searchStart = 0);
366         int lowerBoundScaledX(int origX, int searchStart = 0);
367         int upperBoundScaledY(int origY, int searchStart = 0);
368         int lowerBoundScaledY(int origY, int searchStart = 0);
369         int scaledY(int origY, int searchStart = 0);
370
371         RefPtr<SharedBuffer> m_data; // The encoded data.
372         Vector<ImageFrame, 1> m_frameBufferCache;
373         // FIXME: Do we need m_colorProfile any more, for any port?
374         ColorProfile m_colorProfile;
375         bool m_scaled;
376         Vector<int> m_scaledColumns;
377         Vector<int> m_scaledRows;
378         bool m_premultiplyAlpha;
379         bool m_ignoreGammaAndColorProfile;
380         ImageOrientation m_orientation;
381
382     private:
383         // Some code paths compute the size of the image as "width * height * 4"
384         // and return it as a (signed) int.  Avoid overflow.
385         static bool isOverSize(unsigned width, unsigned height)
386         {
387             unsigned long long total_size = static_cast<unsigned long long>(width)
388                                           * static_cast<unsigned long long>(height);
389             return total_size > ((1 << 29) - 1);
390         }
391
392         IntSize m_size;
393         bool m_sizeAvailable;
394         int m_maxNumPixels;
395         bool m_isAllDataReceived;
396         bool m_failed;
397     };
398
399 } // namespace WebCore
400
401 #endif