⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gifimagedecoder.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2006 Apple Computer, 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 "GIFImageDecoder.h"#include "GIFImageReader.h"#if PLATFORM(CAIRO) || PLATFORM(QT) || PLATFORM(WX)namespace WebCore {class GIFImageDecoderPrivate{public:    GIFImageDecoderPrivate(GIFImageDecoder* decoder = 0)        : m_reader(decoder)    {        m_readOffset = 0;    }    ~GIFImageDecoderPrivate()    {        m_reader.close();    }    bool decode(const Vector<char>& data,                 GIFImageDecoder::GIFQuery query = GIFImageDecoder::GIFFullQuery,                unsigned int haltFrame = -1)    {        return m_reader.read((const unsigned char*)data.data() + m_readOffset, data.size() - m_readOffset,                              query,                             haltFrame);    }    unsigned frameCount() const { return m_reader.images_count; }    int repetitionCount() const { return m_reader.loop_count; }    void setReadOffset(unsigned o) { m_readOffset = o; }    bool isTransparent() const { return m_reader.frame_reader->is_transparent; }    void getColorMap(unsigned char*& map, unsigned& size) const {        if (m_reader.frame_reader->is_local_colormap_defined) {            map = m_reader.frame_reader->local_colormap;            size = (unsigned)m_reader.frame_reader->local_colormap_size;        } else {            map = m_reader.global_colormap;            size = m_reader.global_colormap_size;        }    }    unsigned frameXOffset() const { return m_reader.frame_reader->x_offset; }    unsigned frameYOffset() const { return m_reader.frame_reader->y_offset; }    unsigned frameWidth() const { return m_reader.frame_reader->width; }    unsigned frameHeight() const { return m_reader.frame_reader->height; }    int transparentPixel() const { return m_reader.frame_reader->tpixel; }    unsigned duration() const { return m_reader.frame_reader->delay_time; }private:    GIFImageReader m_reader;    unsigned m_readOffset;};GIFImageDecoder::GIFImageDecoder(): m_frameCountValid(true), m_repetitionCount(cAnimationLoopOnce), m_reader(0){}GIFImageDecoder::~GIFImageDecoder(){    delete m_reader;}// Take the data and store it.void GIFImageDecoder::setData(SharedBuffer* data, bool allDataReceived){    if (m_failed)        return;    // Cache our new data.    ImageDecoder::setData(data, allDataReceived);    // Our frame count is now unknown.    m_frameCountValid = false;    // Create the GIF reader.    if (!m_reader && !m_failed)        m_reader = new GIFImageDecoderPrivate(this);}// Whether or not the size information has been decoded yet.bool GIFImageDecoder::isSizeAvailable() const{    // If we have pending data to decode, send it to the GIF reader now.    if (!m_sizeAvailable && m_reader) {        if (m_failed)            return false;        // The decoder will go ahead and aggressively consume everything up until the first        // size is encountered.        decode(GIFSizeQuery, 0);    }    return m_sizeAvailable;}// The total number of frames for the image.  Will scan the image data for the answer// (without necessarily decoding all of the individual frames).int GIFImageDecoder::frameCount(){    // If the decoder had an earlier error, we will just return what we had decoded    // so far.    if (!m_frameCountValid) {        // FIXME: Scanning all the data has O(n^2) behavior if the data were to come in really        // slowly.  Might be interesting to try to clone our existing read session to preserve        // state, but for now we just crawl all the data.  Note that this is no worse than what        // ImageIO does on Mac right now (it also crawls all the data again).        GIFImageDecoderPrivate reader;        reader.decode(m_data->buffer(), GIFFrameCountQuery);        m_frameCountValid = true;        m_frameBufferCache.resize(reader.frameCount());    }    return m_frameBufferCache.size();}// The number of repetitions to perform for an animation loop.int GIFImageDecoder::repetitionCount() const{    // This value can arrive at any point in the image data stream.  Most GIFs    // in the wild declare it near the beginning of the file, so it usually is    // set by the time we've decoded the size, but (depending on the GIF and the    // packets sent back by the webserver) not always.  Our caller is    // responsible for waiting until image decoding has finished to ask this if    // it needs an authoritative answer.  In the meantime, we should default to    // "loop once".    if (m_reader) {        // Added wrinkle: ImageSource::clear() may destroy the reader, making        // the result from the reader _less_ authoritative on future calls.  To        // detect this, the reader returns cLoopCountNotSeen (-2) instead of        // cAnimationLoopOnce (-1) when its current incarnation hasn't actually        // seen a loop count yet; in this case we return our previously-cached        // value.        const int repetitionCount = m_reader->repetitionCount();        if (repetitionCount != cLoopCountNotSeen)            m_repetitionCount = repetitionCount;    }    return m_repetitionCount;}RGBA32Buffer* GIFImageDecoder::frameBufferAtIndex(size_t index){    if (index >= frameCount())        return 0;    RGBA32Buffer& frame = m_frameBufferCache[index];    if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)        // Decode this frame.        decode(GIFFullQuery, index+1);    return &frame;}void GIFImageDecoder::clearFrameBufferCache(size_t clearBeforeFrame){    // In some cases, like if the decoder was destroyed while animating, we    // can be asked to clear more frames than we currently have.    if (m_frameBufferCache.isEmpty())        return; // Nothing to do.    // The "-1" here is tricky.  It does not mean that |clearBeforeFrame| is the    // last frame we wish to preserve, but rather that we never want to clear    // the very last frame in the cache: it's empty (so clearing it is    // pointless), it's partial (so we don't want to clear it anyway), or the    // cache could be enlarged with a future setData() call and it could be    // needed to construct the next frame (see comments below).  Callers can    // always use ImageSource::clear(true, ...) to completely free the memory in    // this case.    clearBeforeFrame = std::min(clearBeforeFrame, m_frameBufferCache.size() - 1);    const Vector<RGBA32Buffer>::iterator end(m_frameBufferCache.begin() + clearBeforeFrame);    // We need to preserve frames such that:    //   * We don't clear |end|    //   * We don't clear the frame we're currently decoding    //   * We don't clear any frame from which a future initFrameBuffer() call    //     will copy bitmap data    // All other frames can be cleared.  Because of the constraints on when    // ImageSource::clear() can be called (see ImageSource.h), we're guaranteed    // not to have non-empty frames after the frame we're currently decoding.    // So, scan backwards from |end| as follows:    //   * If the frame is empty, we're still past any frames we care about.    //   * If the frame is complete, but is DisposeOverwritePrevious, we'll    //     skip over it in future initFrameBuffer() calls.  We can clear it    //     unless it's |end|, and keep scanning.  For any other disposal method,    //     stop scanning, as we've found the frame initFrameBuffer() will need    //     next.    //   * If the frame is partial, we're decoding it, so don't clear it; if it    //     has a disposal method other than DisposeOverwritePrevious, stop    //     scanning, as we'll only need this frame when decoding the next one.    Vector<RGBA32Buffer>::iterator i(end);    for (; (i != m_frameBufferCache.begin()) && ((i->status() == RGBA32Buffer::FrameEmpty) || (i->disposalMethod() == RGBA32Buffer::DisposeOverwritePrevious)); --i) {        if ((i->status() == RGBA32Buffer::FrameComplete) && (i != end))            i->clear();    }    // Now |i| holds the last frame we need to preserve; clear prior frames.    for (Vector<RGBA32Buffer>::iterator j(m_frameBufferCache.begin()); j != i; ++j) {        ASSERT(j->status() != RGBA32Buffer::FramePartial);        if (j->status() != RGBA32Buffer::FrameEmpty)            j->clear();    }}// Feed data to the GIF reader.void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame) const{    if (m_failed)        return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -