| OLD | NEW |
| (Empty) |
| 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 ImageDecoder_h | |
| 28 #define ImageDecoder_h | |
| 29 | |
| 30 #include "SkColorPriv.h" | |
| 31 #include "core/platform/graphics/ImageSource.h" | |
| 32 #include "core/platform/graphics/skia/NativeImageSkia.h" | |
| 33 #include "platform/PlatformScreen.h" | |
| 34 #include "platform/SharedBuffer.h" | |
| 35 #include "platform/geometry/IntRect.h" | |
| 36 #include "public/platform/Platform.h" | |
| 37 #include "wtf/Assertions.h" | |
| 38 #include "wtf/RefPtr.h" | |
| 39 #include "wtf/text/WTFString.h" | |
| 40 #include "wtf/Vector.h" | |
| 41 | |
| 42 #if USE(QCMSLIB) | |
| 43 #include "qcms.h" | |
| 44 #if OS(MACOSX) | |
| 45 #include <ApplicationServices/ApplicationServices.h> | |
| 46 #include "core/platform/graphics/cg/GraphicsContextCG.h" | |
| 47 #include "wtf/RetainPtr.h" | |
| 48 #endif | |
| 49 #endif | |
| 50 | |
| 51 namespace WebCore { | |
| 52 | |
| 53 // ImageFrame represents the decoded image data. This buffer is what all | |
| 54 // decoders write a single frame into. | |
| 55 class ImageFrame { | |
| 56 public: | |
| 57 enum Status { FrameEmpty, FramePartial, FrameComplete }; | |
| 58 enum DisposalMethod { | |
| 59 // If you change the numeric values of these, make sure you audit | |
| 60 // all users, as some users may cast raw values to/from these | |
| 61 // constants. | |
| 62 DisposeNotSpecified, // Leave frame in framebuffer | |
| 63 DisposeKeep, // Leave frame in framebuffer | |
| 64 DisposeOverwriteBgcolor, // Clear frame to fully transparent | |
| 65 DisposeOverwritePrevious // Clear frame to previous framebuffer cont
ents | |
| 66 }; | |
| 67 // Indicates how non-opaque pixels in the current frame rectangle | |
| 68 // are blended with those in the previous frame. | |
| 69 // Notes: | |
| 70 // * GIF always uses 'BlendAtopPreviousFrame'. | |
| 71 // * WebP also uses the 'BlendAtopBgcolor' option. This is useful for | |
| 72 // cases where one wants to transform a few opaque pixels of the | |
| 73 // previous frame into non-opaque pixels in the current frame. | |
| 74 enum AlphaBlendSource { | |
| 75 // Blend non-opaque pixels atop the corresponding pixels in the | |
| 76 // initial buffer state (i.e. any previous frame buffer after having | |
| 77 // been properly disposed). | |
| 78 BlendAtopPreviousFrame, | |
| 79 | |
| 80 // Blend non-opaque pixels against fully transparent (i.e. simply | |
| 81 // overwrite the corresponding pixels). | |
| 82 BlendAtopBgcolor, | |
| 83 }; | |
| 84 typedef uint32_t PixelData; | |
| 85 | |
| 86 ImageFrame(); | |
| 87 | |
| 88 ImageFrame(const ImageFrame& other) { operator=(other); } | |
| 89 | |
| 90 // For backends which refcount their data, this operator doesn't need to | |
| 91 // create a new copy of the image data, only increase the ref count. | |
| 92 ImageFrame& operator=(const ImageFrame& other); | |
| 93 | |
| 94 // These do not touch other metadata, only the raw pixel data. | |
| 95 void clearPixelData(); | |
| 96 void zeroFillPixelData(); | |
| 97 void zeroFillFrameRect(const IntRect&); | |
| 98 | |
| 99 // Makes this frame have an independent copy of the provided image's | |
| 100 // pixel data, so that modifications in one frame are not reflected in | |
| 101 // the other. Returns whether the copy succeeded. | |
| 102 bool copyBitmapData(const ImageFrame&); | |
| 103 | |
| 104 // Copies the pixel data at [(startX, startY), (endX, startY)) to the | |
| 105 // same X-coordinates on each subsequent row up to but not including | |
| 106 // endY. | |
| 107 void copyRowNTimes(int startX, int endX, int startY, int endY) | |
| 108 { | |
| 109 ASSERT(startX < width()); | |
| 110 ASSERT(endX <= width()); | |
| 111 ASSERT(startY < height()); | |
| 112 ASSERT(endY <= height()); | |
| 113 const int rowBytes = (endX - startX) * sizeof(PixelData); | |
| 114 const PixelData* const startAddr = getAddr(startX, startY); | |
| 115 for (int destY = startY + 1; destY < endY; ++destY) | |
| 116 memcpy(getAddr(startX, destY), startAddr, rowBytes); | |
| 117 } | |
| 118 | |
| 119 // Allocates space for the pixel data. Must be called before any pixels | |
| 120 // are written. Must only be called once. Returns whether allocation | |
| 121 // succeeded. | |
| 122 bool setSize(int newWidth, int newHeight); | |
| 123 | |
| 124 // Returns a caller-owned pointer to the underlying native image data. | |
| 125 // (Actual use: This pointer will be owned by BitmapImage and freed in | |
| 126 // FrameData::clear()). | |
| 127 PassRefPtr<NativeImageSkia> asNewNativeImage() const; | |
| 128 | |
| 129 bool hasAlpha() const; | |
| 130 const IntRect& originalFrameRect() const { return m_originalFrameRect; } | |
| 131 Status status() const { return m_status; } | |
| 132 unsigned duration() const { return m_duration; } | |
| 133 DisposalMethod disposalMethod() const { return m_disposalMethod; } | |
| 134 AlphaBlendSource alphaBlendSource() const { return m_alphaBlendSource; } | |
| 135 bool premultiplyAlpha() const { return m_premultiplyAlpha; } | |
| 136 SkBitmap::Allocator* allocator() const { return m_allocator; } | |
| 137 const SkBitmap& getSkBitmap() const { return m_bitmap->bitmap(); } | |
| 138 // Returns true if the pixels changed, but the bitmap has not yet been n
otified. | |
| 139 bool pixelsChanged() const { return m_pixelsChanged; } | |
| 140 | |
| 141 size_t requiredPreviousFrameIndex() const | |
| 142 { | |
| 143 ASSERT(m_requiredPreviousFrameIndexValid); | |
| 144 return m_requiredPreviousFrameIndex; | |
| 145 } | |
| 146 #if !ASSERT_DISABLED | |
| 147 bool requiredPreviousFrameIndexValid() const { return m_requiredPrevious
FrameIndexValid; } | |
| 148 #endif | |
| 149 void setHasAlpha(bool alpha); | |
| 150 void setOriginalFrameRect(const IntRect& r) { m_originalFrameRect = r; } | |
| 151 void setStatus(Status); | |
| 152 void setDuration(unsigned duration) { m_duration = duration; } | |
| 153 void setDisposalMethod(DisposalMethod disposalMethod) { m_disposalMethod
= disposalMethod; } | |
| 154 void setAlphaBlendSource(AlphaBlendSource alphaBlendSource) { m_alphaBle
ndSource = alphaBlendSource; } | |
| 155 void setPremultiplyAlpha(bool premultiplyAlpha) { m_premultiplyAlpha = p
remultiplyAlpha; } | |
| 156 void setMemoryAllocator(SkBitmap::Allocator* allocator) { m_allocator =
allocator; } | |
| 157 void setSkBitmap(const SkBitmap& bitmap) { m_bitmap = NativeImageSkia::c
reate(bitmap); } | |
| 158 // The pixelsChanged flag needs to be set when the raw pixel data was di
rectly modified | |
| 159 // (e.g. through a pointer or setRGBA). The flag is usually set after a
batch of changes was made. | |
| 160 void setPixelsChanged(bool pixelsChanged) { m_pixelsChanged = pixelsChan
ged; } | |
| 161 | |
| 162 void setRequiredPreviousFrameIndex(size_t previousFrameIndex) | |
| 163 { | |
| 164 m_requiredPreviousFrameIndex = previousFrameIndex; | |
| 165 #if !ASSERT_DISABLED | |
| 166 m_requiredPreviousFrameIndexValid = true; | |
| 167 #endif | |
| 168 } | |
| 169 | |
| 170 inline PixelData* getAddr(int x, int y) | |
| 171 { | |
| 172 return m_bitmap->bitmap().getAddr32(x, y); | |
| 173 } | |
| 174 | |
| 175 inline void setRGBA(int x, int y, unsigned r, unsigned g, unsigned b, un
signed a) | |
| 176 { | |
| 177 setRGBA(getAddr(x, y), r, g, b, a); | |
| 178 } | |
| 179 | |
| 180 static const unsigned div255 = static_cast<unsigned>(1.0 / 255 * (1 << 2
4)) + 1; | |
| 181 | |
| 182 inline void setRGBA(PixelData* dest, unsigned r, unsigned g, unsigned b,
unsigned a) | |
| 183 { | |
| 184 if (m_premultiplyAlpha && a < 255) { | |
| 185 if (!a) { | |
| 186 *dest = 0; | |
| 187 return; | |
| 188 } | |
| 189 | |
| 190 unsigned alpha = a * div255; | |
| 191 r = (r * alpha) >> 24; | |
| 192 g = (g * alpha) >> 24; | |
| 193 b = (b * alpha) >> 24; | |
| 194 } | |
| 195 | |
| 196 // Call the "NoCheck" version since we may deliberately pass non-pre
multiplied | |
| 197 // values, and we don't want an assert. | |
| 198 *dest = SkPackARGB32NoCheck(a, r, g, b); | |
| 199 } | |
| 200 | |
| 201 inline void setRGBARaw(PixelData* dest, unsigned r, unsigned g, unsigned
b, unsigned a) | |
| 202 { | |
| 203 *dest = SkPackARGB32NoCheck(a, r, g, b); | |
| 204 } | |
| 205 | |
| 206 // Notifies the SkBitmap if any pixels changed and resets the flag. | |
| 207 inline void notifyBitmapIfPixelsChanged() | |
| 208 { | |
| 209 if (m_pixelsChanged) | |
| 210 m_bitmap->bitmap().notifyPixelsChanged(); | |
| 211 m_pixelsChanged = false; | |
| 212 } | |
| 213 | |
| 214 private: | |
| 215 int width() const | |
| 216 { | |
| 217 return m_bitmap->bitmap().width(); | |
| 218 } | |
| 219 | |
| 220 int height() const | |
| 221 { | |
| 222 return m_bitmap->bitmap().height(); | |
| 223 } | |
| 224 | |
| 225 RefPtr<NativeImageSkia> m_bitmap; | |
| 226 SkBitmap::Allocator* m_allocator; | |
| 227 bool m_hasAlpha; | |
| 228 // This will always just be the entire buffer except for GIF or WebP | |
| 229 // frames whose original rect was smaller than the overall image size. | |
| 230 IntRect m_originalFrameRect; | |
| 231 Status m_status; | |
| 232 unsigned m_duration; | |
| 233 DisposalMethod m_disposalMethod; | |
| 234 AlphaBlendSource m_alphaBlendSource; | |
| 235 bool m_premultiplyAlpha; | |
| 236 // True if the pixels changed, but the bitmap has not yet been notified. | |
| 237 bool m_pixelsChanged; | |
| 238 | |
| 239 // The frame that must be decoded before this frame can be decoded. | |
| 240 // WTF::kNotFound if this frame doesn't require any previous frame. | |
| 241 // This is used by ImageDecoder::clearCacheExceptFrame(), and will never | |
| 242 // be read for image formats that do not have multiple frames. | |
| 243 size_t m_requiredPreviousFrameIndex; | |
| 244 #if !ASSERT_DISABLED | |
| 245 bool m_requiredPreviousFrameIndexValid; | |
| 246 #endif | |
| 247 }; | |
| 248 | |
| 249 // ImageDecoder is a base for all format-specific decoders | |
| 250 // (e.g. JPEGImageDecoder). This base manages the ImageFrame cache. | |
| 251 // | |
| 252 class ImageDecoder { | |
| 253 WTF_MAKE_NONCOPYABLE(ImageDecoder); WTF_MAKE_FAST_ALLOCATED; | |
| 254 public: | |
| 255 static const size_t noDecodedImageByteLimit = blink::Platform::noDecoded
ImageByteLimit; | |
| 256 | |
| 257 ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAnd
ColorProfileOption gammaAndColorProfileOption, size_t maxDecodedBytes) | |
| 258 : m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied) | |
| 259 , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSo
urce::GammaAndColorProfileIgnored) | |
| 260 , m_maxDecodedBytes(maxDecodedBytes) | |
| 261 , m_sizeAvailable(false) | |
| 262 , m_isAllDataReceived(false) | |
| 263 , m_failed(false) { } | |
| 264 | |
| 265 virtual ~ImageDecoder() { } | |
| 266 | |
| 267 // Returns a caller-owned decoder of the appropriate type. Returns 0 if | |
| 268 // we can't sniff a supported type from the provided data (possibly | |
| 269 // because there isn't enough data yet). | |
| 270 // Sets m_maxDecodedBytes to Platform::maxImageDecodedBytes(). | |
| 271 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSo
urce::AlphaOption, ImageSource::GammaAndColorProfileOption); | |
| 272 | |
| 273 // Returns a decoder with custom maxDecodedSize. | |
| 274 static PassOwnPtr<ImageDecoder> create(const SharedBuffer& data, ImageSo
urce::AlphaOption, ImageSource::GammaAndColorProfileOption, size_t maxDecodedSiz
e); | |
| 275 | |
| 276 virtual String filenameExtension() const = 0; | |
| 277 | |
| 278 bool isAllDataReceived() const { return m_isAllDataReceived; } | |
| 279 | |
| 280 virtual void setData(SharedBuffer* data, bool allDataReceived) | |
| 281 { | |
| 282 if (m_failed) | |
| 283 return; | |
| 284 m_data = data; | |
| 285 m_isAllDataReceived = allDataReceived; | |
| 286 } | |
| 287 | |
| 288 // Lazily-decodes enough of the image to get the size (if possible). | |
| 289 // FIXME: Right now that has to be done by each subclass; factor the | |
| 290 // decode call out and use it here. | |
| 291 virtual bool isSizeAvailable() | |
| 292 { | |
| 293 return !m_failed && m_sizeAvailable; | |
| 294 } | |
| 295 | |
| 296 virtual IntSize size() const { return m_size; } | |
| 297 | |
| 298 // Decoders which downsample images should override this method to | |
| 299 // return the actual decoded size. | |
| 300 virtual IntSize decodedSize() const { return size(); } | |
| 301 | |
| 302 // This will only differ from size() for ICO (where each frame is a | |
| 303 // different icon) or other formats where different frames are different | |
| 304 // sizes. This does NOT differ from size() for GIF or WebP, since | |
| 305 // decoding GIF or WebP composites any smaller frames against previous | |
| 306 // frames to create full-size frames. | |
| 307 virtual IntSize frameSizeAtIndex(size_t) const | |
| 308 { | |
| 309 return size(); | |
| 310 } | |
| 311 | |
| 312 // Returns whether the size is legal (i.e. not going to result in | |
| 313 // overflow elsewhere). If not, marks decoding as failed. | |
| 314 virtual bool setSize(unsigned width, unsigned height) | |
| 315 { | |
| 316 if (sizeCalculationMayOverflow(width, height)) | |
| 317 return setFailed(); | |
| 318 m_size = IntSize(width, height); | |
| 319 m_sizeAvailable = true; | |
| 320 return true; | |
| 321 } | |
| 322 | |
| 323 // Lazily-decodes enough of the image to get the frame count (if | |
| 324 // possible), without decoding the individual frames. | |
| 325 // FIXME: Right now that has to be done by each subclass; factor the | |
| 326 // decode call out and use it here. | |
| 327 virtual size_t frameCount() { return 1; } | |
| 328 | |
| 329 virtual int repetitionCount() const { return cAnimationNone; } | |
| 330 | |
| 331 // Decodes as much of the requested frame as possible, and returns an | |
| 332 // ImageDecoder-owned pointer. | |
| 333 virtual ImageFrame* frameBufferAtIndex(size_t) = 0; | |
| 334 | |
| 335 // Make the best effort guess to check if the requested frame has alpha
channel. | |
| 336 virtual bool frameHasAlphaAtIndex(size_t) const; | |
| 337 | |
| 338 // Whether or not the frame is fully received. | |
| 339 virtual bool frameIsCompleteAtIndex(size_t) const; | |
| 340 | |
| 341 // Duration for displaying a frame in seconds. This method is used by an
imated images only. | |
| 342 virtual float frameDurationAtIndex(size_t) const { return 0; } | |
| 343 | |
| 344 // Number of bytes in the decoded frame requested. Return 0 if not yet d
ecoded. | |
| 345 virtual unsigned frameBytesAtIndex(size_t) const; | |
| 346 | |
| 347 void setIgnoreGammaAndColorProfile(bool flag) { m_ignoreGammaAndColorPro
file = flag; } | |
| 348 bool ignoresGammaAndColorProfile() const { return m_ignoreGammaAndColorP
rofile; } | |
| 349 | |
| 350 ImageOrientation orientation() const { return m_orientation; } | |
| 351 | |
| 352 enum { iccColorProfileHeaderLength = 128 }; | |
| 353 | |
| 354 static bool rgbColorProfile(const char* profileData, unsigned profileLen
gth) | |
| 355 { | |
| 356 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderL
ength); | |
| 357 | |
| 358 return !memcmp(&profileData[16], "RGB ", 4); | |
| 359 } | |
| 360 | |
| 361 static bool inputDeviceColorProfile(const char* profileData, unsigned pr
ofileLength) | |
| 362 { | |
| 363 ASSERT_UNUSED(profileLength, profileLength >= iccColorProfileHeaderL
ength); | |
| 364 | |
| 365 return !memcmp(&profileData[12], "mntr", 4) || !memcmp(&profileData[
12], "scnr", 4); | |
| 366 } | |
| 367 | |
| 368 #if USE(QCMSLIB) | |
| 369 static qcms_profile* qcmsOutputDeviceProfile() | |
| 370 { | |
| 371 static qcms_profile* outputDeviceProfile = 0; | |
| 372 | |
| 373 static bool qcmsInitialized = false; | |
| 374 if (!qcmsInitialized) { | |
| 375 qcmsInitialized = true; | |
| 376 // FIXME: Add optional ICCv4 support. | |
| 377 #if OS(MACOSX) | |
| 378 RetainPtr<CGColorSpaceRef> monitorColorSpace(AdoptCF, CGDisplayC
opyColorSpace(CGMainDisplayID())); | |
| 379 CFDataRef iccProfile(CGColorSpaceCopyICCProfile(monitorColorSpac
e.get())); | |
| 380 if (iccProfile) { | |
| 381 size_t length = CFDataGetLength(iccProfile); | |
| 382 const unsigned char* systemProfile = CFDataGetBytePtr(iccPro
file); | |
| 383 outputDeviceProfile = qcms_profile_from_memory(systemProfile
, length); | |
| 384 } | |
| 385 #else | |
| 386 // FIXME: add support for multiple monitors. | |
| 387 ColorProfile profile; | |
| 388 screenColorProfile(profile); | |
| 389 if (!profile.isEmpty()) | |
| 390 outputDeviceProfile = qcms_profile_from_memory(profile.data(
), profile.size()); | |
| 391 #endif | |
| 392 if (outputDeviceProfile && qcms_profile_is_bogus(outputDevicePro
file)) { | |
| 393 qcms_profile_release(outputDeviceProfile); | |
| 394 outputDeviceProfile = 0; | |
| 395 } | |
| 396 if (!outputDeviceProfile) | |
| 397 outputDeviceProfile = qcms_profile_sRGB(); | |
| 398 if (outputDeviceProfile) | |
| 399 qcms_profile_precache_output_transform(outputDeviceProfile); | |
| 400 } | |
| 401 return outputDeviceProfile; | |
| 402 } | |
| 403 #endif | |
| 404 | |
| 405 // Sets the "decode failure" flag. For caller convenience (since so | |
| 406 // many callers want to return false after calling this), returns false | |
| 407 // to enable easy tailcalling. Subclasses may override this to also | |
| 408 // clean up any local data. | |
| 409 virtual bool setFailed() | |
| 410 { | |
| 411 m_failed = true; | |
| 412 return false; | |
| 413 } | |
| 414 | |
| 415 bool failed() const { return m_failed; } | |
| 416 | |
| 417 // Clears decoded pixel data from all frames except the provided frame. | |
| 418 // Callers may pass WTF::kNotFound to clear all frames. | |
| 419 // Note: If |m_frameBufferCache| contains only one frame, it won't be cl
eared. | |
| 420 // Returns the number of bytes of frame data actually cleared. | |
| 421 virtual size_t clearCacheExceptFrame(size_t); | |
| 422 | |
| 423 // If the image has a cursor hot-spot, stores it in the argument | |
| 424 // and returns true. Otherwise returns false. | |
| 425 virtual bool hotSpot(IntPoint&) const { return false; } | |
| 426 | |
| 427 virtual void setMemoryAllocator(SkBitmap::Allocator* allocator) | |
| 428 { | |
| 429 // FIXME: this doesn't work for images with multiple frames. | |
| 430 if (m_frameBufferCache.isEmpty()) { | |
| 431 m_frameBufferCache.resize(1); | |
| 432 m_frameBufferCache[0].setRequiredPreviousFrameIndex( | |
| 433 findRequiredPreviousFrame(0, false)); | |
| 434 } | |
| 435 m_frameBufferCache[0].setMemoryAllocator(allocator); | |
| 436 } | |
| 437 | |
| 438 protected: | |
| 439 // Calculates the most recent frame whose image data may be needed in | |
| 440 // order to decode frame |frameIndex|, based on frame disposal methods | |
| 441 // and |frameRectIsOpaque|, where |frameRectIsOpaque| signifies whether | |
| 442 // the rectangle of frame at |frameIndex| is known to be opaque. | |
| 443 // If no previous frame's data is required, returns WTF::kNotFound. | |
| 444 // | |
| 445 // This function requires that the previous frame's | |
| 446 // |m_requiredPreviousFrameIndex| member has been set correctly. The | |
| 447 // easiest way to ensure this is for subclasses to call this method and | |
| 448 // store the result on the frame via setRequiredPreviousFrameIndex() | |
| 449 // as soon as the frame has been created and parsed sufficiently to | |
| 450 // determine the disposal method; assuming this happens for all frames | |
| 451 // in order, the required invariant will hold. | |
| 452 // | |
| 453 // Image formats which do not use more than one frame do not need to | |
| 454 // worry about this; see comments on | |
| 455 // ImageFrame::m_requiredPreviousFrameIndex. | |
| 456 size_t findRequiredPreviousFrame(size_t frameIndex, bool frameRectIsOpaq
ue); | |
| 457 | |
| 458 virtual void clearFrameBuffer(size_t frameIndex); | |
| 459 | |
| 460 RefPtr<SharedBuffer> m_data; // The encoded data. | |
| 461 Vector<ImageFrame, 1> m_frameBufferCache; | |
| 462 bool m_premultiplyAlpha; | |
| 463 bool m_ignoreGammaAndColorProfile; | |
| 464 ImageOrientation m_orientation; | |
| 465 | |
| 466 // The maximum amount of memory a decoded image should require. Ideally, | |
| 467 // image decoders should downsample large images to fit under this limit | |
| 468 // (and then return the downsampled size from decodedSize()). Ignoring | |
| 469 // this limit can cause excessive memory use or even crashes on low- | |
| 470 // memory devices. | |
| 471 size_t m_maxDecodedBytes; | |
| 472 | |
| 473 private: | |
| 474 // Some code paths compute the size of the image as "width * height * 4" | |
| 475 // and return it as a (signed) int. Avoid overflow. | |
| 476 static bool sizeCalculationMayOverflow(unsigned width, unsigned height) | |
| 477 { | |
| 478 unsigned long long total_size = static_cast<unsigned long long>(widt
h) | |
| 479 * static_cast<unsigned long long>(heig
ht); | |
| 480 return total_size > ((1 << 29) - 1); | |
| 481 } | |
| 482 | |
| 483 IntSize m_size; | |
| 484 bool m_sizeAvailable; | |
| 485 bool m_isAllDataReceived; | |
| 486 bool m_failed; | |
| 487 }; | |
| 488 | |
| 489 } // namespace WebCore | |
| 490 | |
| 491 #endif | |
| OLD | NEW |