| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 231 |
| 232 ASSERT(isDecodedSizeAvailable()); | 232 ASSERT(isDecodedSizeAvailable()); |
| 233 | 233 |
| 234 size_t frameCount = WebPDemuxGetI(m_demux, WEBP_FF_FRAME_COUNT); | 234 size_t frameCount = WebPDemuxGetI(m_demux, WEBP_FF_FRAME_COUNT); |
| 235 updateAggressivePurging(frameCount); | 235 updateAggressivePurging(frameCount); |
| 236 | 236 |
| 237 return true; | 237 return true; |
| 238 } | 238 } |
| 239 | 239 |
| 240 bool WEBPImageDecoder::initFrameBuffer(size_t frameIndex) { | 240 bool WEBPImageDecoder::initFrameBuffer(size_t frameIndex) { |
| 241 // ImageDecoder::initFrameBuffer does a DCHECK if |frameIndex| exists. |
| 242 if (!ImageDecoder::initFrameBuffer(frameIndex)) |
| 243 return false; |
| 244 |
| 241 ImageFrame& buffer = m_frameBufferCache[frameIndex]; | 245 ImageFrame& buffer = m_frameBufferCache[frameIndex]; |
| 242 if (buffer.getStatus() != ImageFrame::FrameEmpty) // Already initialized. | |
| 243 return true; | |
| 244 | 246 |
| 245 const size_t requiredPreviousFrameIndex = buffer.requiredPreviousFrameIndex(); | 247 const size_t requiredPreviousFrameIndex = buffer.requiredPreviousFrameIndex(); |
| 246 if (requiredPreviousFrameIndex == kNotFound) { | 248 if (requiredPreviousFrameIndex == kNotFound) { |
| 247 // This frame doesn't rely on any previous data. | |
| 248 if (!buffer.setSizeAndColorSpace(size().width(), size().height(), | |
| 249 colorSpace())) | |
| 250 return setFailed(); | |
| 251 m_frameBackgroundHasAlpha = | 249 m_frameBackgroundHasAlpha = |
| 252 !buffer.originalFrameRect().contains(IntRect(IntPoint(), size())); | 250 !buffer.originalFrameRect().contains(IntRect(IntPoint(), size())); |
| 253 } else { | 251 } else { |
| 254 ImageFrame& prevBuffer = m_frameBufferCache[requiredPreviousFrameIndex]; | 252 const ImageFrame& prevBuffer = |
| 255 ASSERT(prevBuffer.getStatus() == ImageFrame::FrameComplete); | 253 m_frameBufferCache[requiredPreviousFrameIndex]; |
| 256 | |
| 257 // Preserve the last frame as the starting state for this frame. We try | |
| 258 // to reuse |prevBuffer| as starting state to avoid copying. | |
| 259 // For BlendAtopPreviousFrame, both frames are required, so we can't | |
| 260 // take over its image data using takeBitmapDataIfWritable. | |
| 261 if ((buffer.getAlphaBlendSource() == ImageFrame::BlendAtopPreviousFrame || | |
| 262 !buffer.takeBitmapDataIfWritable(&prevBuffer)) && | |
| 263 !buffer.copyBitmapData(prevBuffer)) | |
| 264 return setFailed(); | |
| 265 | |
| 266 if (prevBuffer.getDisposalMethod() == ImageFrame::DisposeOverwriteBgcolor) { | |
| 267 // We want to clear the previous frame to transparent, without | |
| 268 // affecting pixels in the image outside of the frame. | |
| 269 const IntRect& prevRect = prevBuffer.originalFrameRect(); | |
| 270 ASSERT(!prevRect.contains(IntRect(IntPoint(), size()))); | |
| 271 buffer.zeroFillFrameRect(prevRect); | |
| 272 } | |
| 273 | |
| 274 m_frameBackgroundHasAlpha = | 254 m_frameBackgroundHasAlpha = |
| 275 prevBuffer.hasAlpha() || | 255 prevBuffer.hasAlpha() || |
| 276 (prevBuffer.getDisposalMethod() == ImageFrame::DisposeOverwriteBgcolor); | 256 (prevBuffer.getDisposalMethod() == ImageFrame::DisposeOverwriteBgcolor); |
| 277 } | 257 } |
| 278 | 258 |
| 279 buffer.setStatus(ImageFrame::FramePartial); | |
| 280 // The buffer is transparent outside the decoded area while the image is | 259 // The buffer is transparent outside the decoded area while the image is |
| 281 // loading. The correct alpha value for the frame will be set when it is fully | 260 // loading. The correct alpha value for the frame will be set when it is fully |
| 282 // decoded. | 261 // decoded. |
| 283 buffer.setHasAlpha(true); | 262 buffer.setHasAlpha(true); |
| 284 return true; | 263 return true; |
| 285 } | 264 } |
| 286 | 265 |
| 266 bool WEBPImageDecoder::canReusePreviousFrameBuffer(size_t frameIndex) const { |
| 267 DCHECK(frameIndex < m_frameBufferCache.size()); |
| 268 return m_frameBufferCache[frameIndex].getAlphaBlendSource() != |
| 269 ImageFrame::BlendAtopPreviousFrame; |
| 270 } |
| 271 |
| 287 size_t WEBPImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) { | 272 size_t WEBPImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) { |
| 288 // If |clearExceptFrame| has status FrameComplete, we preserve that frame. | 273 // If |clearExceptFrame| has status FrameComplete, we preserve that frame. |
| 289 // Otherwise, we preserve the most recent previous frame with status | 274 // Otherwise, we preserve the most recent previous frame with status |
| 290 // FrameComplete whose data will be required to decode |clearExceptFrame|, | 275 // FrameComplete whose data will be required to decode |clearExceptFrame|, |
| 291 // either in initFrameBuffer() or ApplyPostProcessing(). All other frames can | 276 // either in initFrameBuffer() or ApplyPostProcessing(). All other frames can |
| 292 // be cleared. | 277 // be cleared. |
| 293 while ((clearExceptFrame < m_frameBufferCache.size()) && | 278 while ((clearExceptFrame < m_frameBufferCache.size()) && |
| 294 (m_frameBufferCache[clearExceptFrame].getStatus() != | 279 (m_frameBufferCache[clearExceptFrame].getStatus() != |
| 295 ImageFrame::FrameComplete)) | 280 ImageFrame::FrameComplete)) |
| 296 clearExceptFrame = | 281 clearExceptFrame = |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 return false; | 539 return false; |
| 555 } | 540 } |
| 556 // FALLTHROUGH | 541 // FALLTHROUGH |
| 557 default: | 542 default: |
| 558 clear(); | 543 clear(); |
| 559 return setFailed(); | 544 return setFailed(); |
| 560 } | 545 } |
| 561 } | 546 } |
| 562 | 547 |
| 563 } // namespace blink | 548 } // namespace blink |
| OLD | NEW |