diff options
author | Ben Murdoch <benm@google.com> | 2009-08-11 17:01:47 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2009-08-11 18:21:02 +0100 |
commit | 0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch) | |
tree | 2943df35f62d885c89d01063cc528dd73b480fea /WebCore/platform/image-decoders/xbm | |
parent | 7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff) | |
download | external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2 |
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/platform/image-decoders/xbm')
-rw-r--r-- | WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp | 290 | ||||
-rw-r--r-- | WebCore/platform/image-decoders/xbm/XBMImageDecoder.h | 83 |
2 files changed, 322 insertions, 51 deletions
diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp index 3e8ae57..332bc72 100644 --- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp +++ b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.cpp @@ -1,42 +1,278 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * + * 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: - * 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 + * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #include "config.h" #include "XBMImageDecoder.h" - -namespace WebCore + +#include "ASCIICType.h" + +#include <algorithm> +#include <cstdio> + +namespace WebCore { + +XBMImageDecoder::XBMImageDecoder() + : m_decodeOffset(0) + , m_allDataReceived(false) + , m_decodedHeader(false) + , m_dataType(Unknown) + , m_bitsDecoded(0) { +} -bool XBMImageDecoder::isSizeAvailable() const +void XBMImageDecoder::setData(SharedBuffer* data, bool allDataReceived) { - return false; + ImageDecoder::setData(data, allDataReceived); + m_xbmString = data->buffer(); + m_xbmString.append('\0'); + + m_allDataReceived = allDataReceived; } - + +bool XBMImageDecoder::isSizeAvailable() +{ + if (!ImageDecoder::isSizeAvailable() && !m_failed) + decode(true); + + return ImageDecoder::isSizeAvailable(); +} + RGBA32Buffer* XBMImageDecoder::frameBufferAtIndex(size_t index) { - return 0; + if (index) + return 0; + + if (m_frameBufferCache.isEmpty()) + m_frameBufferCache.resize(1); + + // Attempt to get the size if we don't have it yet. + if (!ImageDecoder::isSizeAvailable()) + decode(true); + + // Initialize the framebuffer if needed. + RGBA32Buffer& buffer = m_frameBufferCache[0]; + if (!failed() && ImageDecoder::isSizeAvailable() + && (buffer.status() == RGBA32Buffer::FrameEmpty)) { + if (!buffer.setSize(size().width(), size().height())) { + m_failed = true; + return 0; + } + buffer.setStatus(RGBA32Buffer::FramePartial); + + // For XBMs, the frame always fills the entire image. + buffer.setRect(IntRect(IntPoint(), size())); + } + + // Keep trying to decode until we've got the entire image. + if (buffer.status() == RGBA32Buffer::FramePartial) + decode(false); + + return &buffer; +} + +bool XBMImageDecoder::decodeHeader() +{ + ASSERT(m_decodeOffset <= m_xbmString.size()); + ASSERT(!m_decodedHeader); + + const char* input = m_xbmString.data(); + + // 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.data(); + 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 && isASCIISpace(*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::decode(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 diff --git a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h index 80cfb3f..00f62ce 100644 --- a/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h +++ b/WebCore/platform/image-decoders/xbm/XBMImageDecoder.h @@ -1,26 +1,31 @@ /* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * + * 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: - * 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 + * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef XBMImageDecoder_h @@ -30,17 +35,47 @@ namespace WebCore { - class XBMImageReader; - // This class decodes the XBM image format. class XBMImageDecoder : public ImageDecoder { public: + XBMImageDecoder(); + virtual ~XBMImageDecoder() {} + virtual String filenameExtension() const { return "xbm"; } + virtual void setData(SharedBuffer* data, bool allDataReceived); // Whether or not the size information has been decoded yet. - virtual bool isSizeAvailable() const; - + virtual bool isSizeAvailable(); virtual RGBA32Buffer* frameBufferAtIndex(size_t index); + + private: + // Restricts image size to something "reasonable". + // This protects agains ridiculously large XBMs and prevents bad things + // like overflow of m_bitsDecoded. + static const int maxDimension = 65535; + + // In X10, an array of type "short" is used to declare the image bits, + // but in X11, the type is "char". + enum DataType { + Unknown, + X10, + X11, + }; + + bool decodeHeader(); + bool decodeDatum(uint16_t* result); + bool decodeData(); + void decode(bool sizeOnly); + + // FIXME: Copying all the XBM data just so we can NULL-terminate, just + // so we can use sscanf() and friends, is lame. The decoder should be + // rewritten to operate on m_data directly. + Vector<char> m_xbmString; // Null-terminated copy of the XBM data. + size_t m_decodeOffset; // The current offset in m_xbmString for decoding. + bool m_allDataReceived; + bool m_decodedHeader; + enum DataType m_dataType; + int m_bitsDecoded; }; } // namespace WebCore |