summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/image-decoders/xbm
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/platform/image-decoders/xbm
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_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.cpp290
-rw-r--r--WebCore/platform/image-decoders/xbm/XBMImageDecoder.h83
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