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

📄 xbmimagedecoder.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
字号:
/* * Copyright (c) 2008, 2009, Google 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: *  *     * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. *     * 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. *     * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "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 THE COPYRIGHT * OWNER 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 "XBMImageDecoder.h"#include <algorithm>namespace WebCore {XBMImageDecoder::XBMImageDecoder()    : m_decodeOffset(0)    , m_allDataReceived(false)    , m_decodedHeader(false)    , m_dataType(Unknown)    , m_bitsDecoded(0){}void XBMImageDecoder::setData(SharedBuffer* data, bool allDataReceived){    ImageDecoder::setData(data, allDataReceived);    const Vector<char>& buf = m_data->buffer();    if (buf.size() > m_xbmString.size())        m_xbmString.append(&buf[m_xbmString.size()], buf.size() - m_xbmString.size());    m_allDataReceived = allDataReceived;}bool XBMImageDecoder::isSizeAvailable() const{    // This method should either (a) not be const, or (b) not be expected to    // do anything that changes m_sizeAvailable. The png and jpeg decoders    // get around this with callbacks from external libraries.    //    // FIXME: Find out if we can patch webkit to take care of this.    if (!ImageDecoder::isSizeAvailable() && !m_failed)        const_cast<XBMImageDecoder*>(this)->decodeXBM(true);    return !m_failed && ImageDecoder::isSizeAvailable();}RGBA32Buffer* XBMImageDecoder::frameBufferAtIndex(size_t index){    // Allocate a framebuffer if necessary. New framebuffers have their status    // initialized to RGBA32Buffer::FrameEmpty.    if (m_frameBufferCache.isEmpty())        m_frameBufferCache.resize(1);    RGBA32Buffer& frame = m_frameBufferCache[0];    // Attempt to get the size if we don't have it yet.    if (!ImageDecoder::isSizeAvailable())        decodeXBM(true);        // Size the framebuffer once we know the right size.    if (ImageDecoder::isSizeAvailable() &&        frame.status() == RGBA32Buffer::FrameEmpty) {        if (!frame.setSize(size().width(), size().height())) {            m_failed = true;            frame.setStatus(RGBA32Buffer::FrameComplete);            return 0;        }        frame.setStatus(RGBA32Buffer::FramePartial);    }        // Keep trying to decode until we've got the entire image.    if (frame.status() != RGBA32Buffer::FrameComplete)        decodeXBM(false);    return &frame;}bool XBMImageDecoder::decodeHeader(){    ASSERT(m_decodeOffset <= m_xbmString.size());    ASSERT(!m_decodedHeader);    const char* input = m_xbmString.c_str();    // At least 2 "#define <string> <unsigned>" sequences are required. These    // specify the width and height of the image.    int width, height;    if (!ImageDecoder::isSizeAvailable()) {        int count;        if (sscanf(&input[m_decodeOffset], "#define %*s %i #define %*s %i%n",                   &width, &height, &count) != 2)            return false;        // The width and height need to follow some rules.        if (width < 0 || width > maxDimension || height < 0 || height > maxDimension) {            // If this happens, decoding should not continue.            setFailed();            return false;        }        if (!setSize(width, height)) {            setFailed();            return false;        }        m_decodeOffset += count;        ASSERT(m_decodeOffset <= m_xbmString.size());    }    ASSERT(ImageDecoder::isSizeAvailable());    // Now we're looking for something that tells us that we've seen all of the    // "#define <string> <unsigned>" sequences that we're going to. Mozilla    // just looks for " char " or " short ". We'll do the same.    if (m_dataType == Unknown) {        const char* x11hint = " char ";        const char* x11HintLocation = strstr(&input[m_decodeOffset], x11hint);        if (x11HintLocation) {            m_dataType = X11;            m_decodeOffset += ((x11HintLocation - &input[m_decodeOffset]) + strlen(x11hint));        } else {            const char* x10hint = " short ";            const char* x10HintLocation = strstr(&input[m_decodeOffset], x10hint);            if (x10HintLocation) {                m_dataType = X10;                m_decodeOffset += ((x10HintLocation - &input[m_decodeOffset]) + strlen(x10hint));            } else                return false;        }        ASSERT(m_decodeOffset <= m_xbmString.size());    }    // Find the start of the data. Again, we do what mozilla does and just    // look for a '{' in the input.    const char* found = strchr(&input[m_decodeOffset], '{');    if (!found)        return false;    // Advance to character after the '{'    m_decodeOffset += ((found - &input[m_decodeOffset]) + 1);    ASSERT(m_decodeOffset <= m_xbmString.size());    m_decodedHeader = true;    return true;}// The data in an XBM file is provided as an array of either "char" or "short"// values. These values are decoded one at a time using strtoul() and the bits// are used to set the alpha value for the image.//// The value for the color is always set to RGB(0,0,0), the alpha value takes// care of whether or not the pixel shows up.//// Since the data may arrive in chunks, and many prefixes of valid numbers are// themselves valid numbers, this code needs to check to make sure that the// value is not truncated. This is done by consuming space after the value// read until a ',' or a '}' occurs. In a valid XBM, one of these characters// will occur after each value.//// The checks after strtoul are based on Mozilla's nsXBMDecoder.cpp.bool XBMImageDecoder::decodeDatum(uint16_t* result){    const char* input = m_xbmString.c_str();    char* endPtr;    const uint16_t value = strtoul(&input[m_decodeOffset], &endPtr, 0);    // End of input or couldn't decode anything, can't go any further.    if (endPtr == &input[m_decodeOffset] || !*endPtr)        return false;    // Possibly a hex value truncated at "0x". Need more data.    if (value == 0 && (*endPtr == 'x' || *endPtr == 'X'))        return false;    // Skip whitespace    while (*endPtr && isspace(*endPtr))        ++endPtr;    // Out of input, don't know what comes next.    if (!*endPtr)        return false;    // If the next non-whitespace character is not one of these, it's an error.    // Every valid entry in the data array needs to be followed by ',' or '}'.    if (*endPtr != ',' && *endPtr != '}') {        setFailed();        return false;    }    // At this point we have a value.    *result = value;    // Skip over the decoded value plus the delimiter (',' or '}').    m_decodeOffset += ((endPtr - &input[m_decodeOffset]) + 1);    ASSERT(m_decodeOffset <= m_xbmString.size());    return true;}bool XBMImageDecoder::decodeData(){    ASSERT(m_decodeOffset <= m_xbmString.size());    ASSERT(m_decodedHeader && !m_frameBufferCache.isEmpty());    RGBA32Buffer& frame = m_frameBufferCache[0];    ASSERT(frame.status() == RGBA32Buffer::FramePartial);    const int bitsPerRow = size().width();    ASSERT(m_dataType != Unknown);    while (m_bitsDecoded < (size().width() * size().height())) {        uint16_t value;        if (!decodeDatum(&value))            return false;        int x = m_bitsDecoded % bitsPerRow;        const int y = m_bitsDecoded / bitsPerRow;        // How many bits will be written?        const int bits = std::min(bitsPerRow - x, (m_dataType == X11) ? 8 : 16);        // Only the alpha channel matters here, so the color values are always        // set to 0.        for (int i = 0; i < bits; ++i)            frame.setRGBA(x++, y, 0, 0, 0, value & (1 << i) ? 255 : 0);        m_bitsDecoded += bits;    }    frame.setStatus(RGBA32Buffer::FrameComplete);    return true;}// Decode as much as we can of the XBM file.void XBMImageDecoder::decodeXBM(bool sizeOnly){    if (failed())        return;    bool decodeResult = false;    if (!m_decodedHeader)        decodeResult = decodeHeader();    if (m_decodedHeader && !sizeOnly)        decodeResult = decodeData();    // The header or the data could not be decoded, but there is no more    // data: decoding has failed.    if (!decodeResult && m_allDataReceived)        setFailed();}} // namespace WebCore

⌨️ 快捷键说明

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