This is part of r 18111 commit - Use the Qt image
authorzack <zack@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 10 Dec 2006 00:44:17 +0000 (00:44 +0000)
committerzack <zack@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 10 Dec 2006 00:44:17 +0000 (00:44 +0000)
loading framework.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@18113 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/platform/graphics/qt/ImageDecoderQt.cpp [new file with mode: 0644]
WebCore/platform/graphics/qt/ImageDecoderQt.h [new file with mode: 0644]

diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
new file mode 100644 (file)
index 0000000..9dbaa30
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2006 Friedemann Kleint <fkleint@trolltech.com>
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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 "ImageDecoderQt.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QBuffer>
+
+#include <QtGui/QImageReader>
+#include <qdebug.h>
+
+namespace {
+    const  QImage::Format DesiredFormat = QImage::Format_ARGB32;
+    const  bool debugImageDecoderQt = false;
+}
+
+namespace WebCore {
+ImageDecoderQt::ImageData::ImageData(const QImage& image, ImageState imageState, int duration) :
+    m_image(image), m_imageState(imageState), m_duration(duration)
+{
+}
+
+// Context, maintains IODevice on a data buffer.
+class ImageDecoderQt::ReadContext {
+public:
+
+    enum LoadMode {
+        // Load images incrementally. This is still experimental and
+        // will cause the image plugins to report errors.
+        // Also note that as of Qt 4.2.2, the JPEG loader does not return error codes
+        // on "preliminary end of data".
+        LoadIncrementally,
+            // Load images only if  all data have been received
+            LoadComplete };
+
+    ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target);
+
+    enum ReadResult { ReadEOF, ReadFailed, ReadPartial, ReadComplete };
+
+    // Append data and read out all images. Returns the result
+    // of the last read operation, so, even if  ReadPartial is returned,
+    // a few images might have been read.
+    ReadResult read(bool allDataReceived);
+
+private:
+    enum IncrementalReadResult { IncrementalReadFailed, IncrementalReadPartial, IncrementalReadComplete };
+    // Incrementally read an image
+    IncrementalReadResult readImageLines(ImageData &);
+
+    const LoadMode m_loadMode;
+
+    QByteArray m_data;
+    QBuffer m_buffer;
+    QImageReader m_reader;
+
+    ImageList &m_target;
+
+    // Detected data format of the stream
+    enum QImage::Format m_dataFormat;
+    QSize m_size;
+
+};
+
+ImageDecoderQt::ReadContext::ReadContext(const IncomingData & data, LoadMode loadMode, ImageList &target) :
+    m_loadMode(loadMode),
+    m_data(data.data(), data.size()),
+    m_buffer(&m_data),
+    m_reader(&m_buffer),
+    m_target(target),
+    m_dataFormat(QImage::Format_Invalid)
+{
+    m_buffer.open(QIODevice::ReadOnly);
+}
+
+
+ImageDecoderQt::ReadContext::ReadResult
+        ImageDecoderQt::ReadContext::read(bool allDataReceived)
+{
+    // Complete mode: Read only all all data received
+    if (m_loadMode == LoadComplete && !allDataReceived)
+        return ReadPartial;
+
+    // Attempt to read out all images
+    while (true) {
+        if (m_target.empty() || m_target.back().m_imageState == ImageComplete) {
+            // Start a new image.
+            if (!m_reader.canRead())
+                return ReadEOF;
+
+            // Attempt to construct an empty image of the matching size and format
+            // for efficient reading
+            QImage newImage = m_dataFormat != QImage::Format_Invalid  ?
+                          QImage(m_size,m_dataFormat) : QImage();
+            m_target.push_back(ImageData(newImage));
+        }
+
+        // read chunks
+        switch (readImageLines(m_target.back())) {
+        case IncrementalReadFailed:
+            m_target.pop_back();
+            return ReadFailed;
+        case IncrementalReadPartial:
+            return ReadPartial;
+        case IncrementalReadComplete:
+            m_target.back().m_imageState = ImageComplete;
+            //store for next
+            m_dataFormat = m_target.back().m_image.format();
+            m_size = m_target.back().m_image.size();
+            const bool supportsAnimation = m_reader.supportsAnimation();
+
+            if (debugImageDecoderQt)
+                qDebug() << "readImage(): #" << m_target.size() << " complete, " << m_size << " format " << m_dataFormat
+                <<  " supportsAnimation=" <<  supportsAnimation ;
+            // No point in readinfg further
+            if (!supportsAnimation)
+                return ReadComplete;
+
+            break;
+        }
+    }
+    return ReadComplete;
+}
+
+
+
+ImageDecoderQt::ReadContext::IncrementalReadResult
+        ImageDecoderQt::ReadContext::readImageLines(ImageData &imageData)
+{
+    // TODO: Implement incremental reading here,
+    // set state to reflect complete header, etc.
+    // For now, we read the whole image.
+
+    const qint64 startPos = m_buffer.pos ();
+    // Oops, failed. Rewind.
+    if (!m_reader.read(&imageData.m_image)) {
+        m_buffer.seek(startPos);
+        const bool gotHeader = imageData.m_image.size().width();
+
+        if (debugImageDecoderQt)
+            qDebug() << "readImageLines(): read() failed: " << m_reader.errorString()
+                << " got header=" << gotHeader;
+        // [Experimental] Did we manage to read the header?
+        if (gotHeader) {
+            imageData.m_imageState = ImageHeaderValid;
+            return IncrementalReadPartial;
+        }
+        return IncrementalReadFailed;
+    }
+    imageData.m_duration = m_reader.nextImageDelay();
+    return IncrementalReadComplete;
+}
+
+
+// ImageDecoderQt
+ImageDecoderQt::ImageDecoderQt( )
+{
+}
+
+ImageDecoderQt::~ImageDecoderQt()
+{
+}
+
+bool ImageDecoderQt::hasFirstImageHeader() const
+{
+    return  !m_imageList.empty() && m_imageList[0].m_imageState >= ImageHeaderValid;
+}
+
+void ImageDecoderQt::reset()
+{
+    m_failed = false;
+    m_imageList.clear();
+    m_sizeAvailable = false;
+    m_size = IntSize(-1, -1);
+}
+
+void ImageDecoderQt::setData(const IncomingData &data, bool allDataReceived)
+{
+    reset();
+    ReadContext readContext(data, ReadContext::LoadComplete, m_imageList);
+
+    if (debugImageDecoderQt)
+        qDebug() << " setData " << data.size() << " image bytes, complete=" << allDataReceived;
+
+    const  ReadContext::ReadResult readResult =  readContext.read(allDataReceived);
+
+    if (debugImageDecoderQt)
+        qDebug()  << " read returns " << readResult;
+
+    switch ( readResult)    {
+    case ReadContext::ReadFailed:
+        m_failed = true;
+        break;
+    case ReadContext::ReadEOF:
+    case ReadContext::ReadPartial:
+    case ReadContext::ReadComplete:
+        // Did we read anything - try to set the size.
+        if (hasFirstImageHeader()) {
+            m_sizeAvailable = true;
+            m_size = m_imageList[0].m_image.size();
+        }
+        break;
+    }
+}
+
+
+bool ImageDecoderQt::isSizeAvailable() const
+{
+    if (debugImageDecoderQt)
+        qDebug() << " ImageDecoderQt::isSizeAvailable() returns" << m_sizeAvailable;
+    return m_sizeAvailable;
+}
+
+int ImageDecoderQt::frameCount() const
+{
+    return m_imageList.size();
+}
+
+
+int ImageDecoderQt::repetitionCount() const
+{
+    // TODO: Am I Moses?!
+    return cAnimationNone;
+}
+
+
+bool ImageDecoderQt::ImageDecoderQt::supportsAlpha() const
+{
+    return hasFirstImageHeader() && m_imageList[0].m_image.hasAlphaChannel();
+}
+
+int ImageDecoderQt::duration(size_t index) const
+{
+    if (index >= m_imageList.size())
+        return 0;
+    return  m_imageList[index].m_duration;
+}
+
+RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
+{
+    Q_ASSERT("use imageAtIndex instead");
+    return 0;
+}
+
+const QImage* ImageDecoderQt::imageAtIndex(size_t index) const
+{
+    if (debugImageDecoderQt)
+        qDebug() << "ImageDecoderQt::imageAtIndex(" << index << ')';
+
+    if (index >= m_imageList.size())
+        return 0;
+    return &m_imageList[index].m_image;
+}
+
+}
+
+// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
new file mode 100644 (file)
index 0000000..6f2c92f
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2006 Friedemann Kleint <fkleint@trolltech.com>
+ * Copyright (C) 2006 Trolltech ASA
+ *
+ * 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.
+ */
+
+#ifndef IMAGEDECODERQT_H_
+#define IMAGEDECODERQT_H_
+
+#include "ImageDecoder.h"
+#include <QtCore/QList>
+#include <QtGui/QImage>
+
+namespace WebCore {
+
+
+class ImageDecoderQt : public ImageDecoder
+{
+    ImageDecoderQt(const ImageDecoderQt&);
+    ImageDecoderQt &operator=(const ImageDecoderQt&);
+public:
+    ImageDecoderQt();
+    ~ImageDecoderQt();
+
+    typedef Vector<char> IncomingData;
+
+    virtual void setData(const IncomingData& data, bool allDataReceived);
+
+    virtual bool isSizeAvailable() const;
+
+    virtual int frameCount() const;
+
+
+    virtual int repetitionCount() const;
+
+
+    virtual RGBA32Buffer* frameBufferAtIndex(size_t index);
+
+    const QImage* imageAtIndex(size_t index) const;
+
+    virtual bool supportsAlpha() const;
+
+    int duration(size_t index) const;
+private:
+    class ReadContext;
+    void reset();
+    bool hasFirstImageHeader() const;
+
+    enum ImageState {
+        // Started image reading
+        ImagePartial,
+            // Header (size / alpha) are known
+            ImageHeaderValid,
+            // Image is complete
+            ImageComplete };
+
+    struct ImageData {
+        ImageData(const QImage& image, ImageState imageState = ImagePartial, int duration=0);
+        QImage m_image;
+        ImageState m_imageState;
+        int m_duration;
+    };
+
+    typedef QList<ImageData> ImageList;
+    ImageList m_imageList;
+};
+
+
+
+}
+
+#endif
+