📄 bitmapimage.cpp
字号:
/* * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include "BitmapImage.h"#include "FloatRect.h"#include "ImageObserver.h"#include "IntRect.h"#include "MIMETypeRegistry.h"#include "PlatformString.h"#include "Timer.h"#include <wtf/CurrentTime.h>#include <wtf/Vector.h>namespace WebCore {static int frameBytes(const IntSize& frameSize){ return frameSize.width() * frameSize.height() * 4;}BitmapImage::BitmapImage(ImageObserver* observer) : Image(observer) , m_currentFrame(0) , m_frames(0) , m_frameTimer(0) , m_repetitionCount(cAnimationNone) , m_repetitionCountStatus(Unknown) , m_repetitionsComplete(0) , m_desiredFrameStartTime(0) , m_isSolidColor(false) , m_checkedForSolidColor(false) , m_animationFinished(false) , m_allDataReceived(false) , m_haveSize(false) , m_sizeAvailable(false) , m_hasUniformFrameSize(true) , m_decodedSize(0) , m_haveFrameCount(false) , m_frameCount(0){ initPlatformData();}BitmapImage::~BitmapImage(){ invalidatePlatformData(); stopAnimation();}void BitmapImage::destroyDecodedData(bool destroyAll){ int framesCleared = 0; const size_t clearBeforeFrame = destroyAll ? m_frames.size() : m_currentFrame; for (size_t i = 0; i < clearBeforeFrame; ++i) { // The underlying frame isn't actually changing (we're just trying to // save the memory for the framebuffer data), so we don't need to clear // the metadata. if (m_frames[i].clear(false)) ++framesCleared; } destroyMetadataAndNotify(framesCleared); m_source.clear(destroyAll, clearBeforeFrame, m_data.get(), m_allDataReceived); return;}void BitmapImage::destroyDecodedDataIfNecessary(bool destroyAll){ // Animated images >5MB are considered large enough that we'll only hang on // to one frame at a time. static const unsigned cLargeAnimationCutoff = 5242880; if (frameCount() * frameBytes(m_size) > cLargeAnimationCutoff) destroyDecodedData(destroyAll);}void BitmapImage::destroyMetadataAndNotify(int framesCleared){ m_isSolidColor = false; invalidatePlatformData(); const int deltaBytes = framesCleared * -frameBytes(m_size); m_decodedSize += deltaBytes; if (deltaBytes && imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes);}void BitmapImage::cacheFrame(size_t index){ size_t numFrames = frameCount(); ASSERT(m_decodedSize == 0 || numFrames > 1); if (m_frames.size() < numFrames) m_frames.grow(numFrames); m_frames[index].m_frame = m_source.createFrameAtIndex(index); if (numFrames == 1 && m_frames[index].m_frame) checkForSolidColor(); m_frames[index].m_haveMetadata = true; m_frames[index].m_isComplete = m_source.frameIsCompleteAtIndex(index); if (repetitionCount(false) != cAnimationNone) m_frames[index].m_duration = m_source.frameDurationAtIndex(index); m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index); const IntSize frameSize(index ? m_source.frameSizeAtIndex(index) : m_size); if (frameSize != m_size) m_hasUniformFrameSize = false; if (m_frames[index].m_frame) { const int deltaBytes = frameBytes(frameSize); m_decodedSize += deltaBytes; if (imageObserver()) imageObserver()->decodedSizeChanged(this, deltaBytes); }}IntSize BitmapImage::size() const{ if (m_sizeAvailable && !m_haveSize) { m_size = m_source.size(); m_haveSize = true; } return m_size;}IntSize BitmapImage::currentFrameSize() const{ if (!m_currentFrame || m_hasUniformFrameSize) return size(); return m_source.frameSizeAtIndex(m_currentFrame);}bool BitmapImage::dataChanged(bool allDataReceived){ // Because we're modifying the current frame, clear its (now possibly // inaccurate) metadata as well. destroyMetadataAndNotify((!m_frames.isEmpty() && m_frames[m_frames.size() - 1].clear(true)) ? 1 : 0); // Feed all the data we've seen so far to the image decoder. m_allDataReceived = allDataReceived; m_source.setData(m_data.get(), allDataReceived); // Clear the frame count. m_haveFrameCount = false; m_hasUniformFrameSize = true; // Image properties will not be available until the first frame of the file // reaches kCGImageStatusIncomplete. return isSizeAvailable();}String BitmapImage::filenameExtension() const{ return m_source.filenameExtension();}size_t BitmapImage::frameCount(){ if (!m_haveFrameCount) { m_haveFrameCount = true; m_frameCount = m_source.frameCount(); } return m_frameCount;}bool BitmapImage::isSizeAvailable(){ if (m_sizeAvailable) return true; m_sizeAvailable = m_source.isSizeAvailable(); return m_sizeAvailable;}NativeImagePtr BitmapImage::frameAtIndex(size_t index){ if (index >= frameCount()) return 0; if (index >= m_frames.size() || !m_frames[index].m_frame) cacheFrame(index); return m_frames[index].m_frame;}bool BitmapImage::frameIsCompleteAtIndex(size_t index){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -