diff options
Diffstat (limited to 'share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp')
-rw-r--r-- | share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp | 157 |
1 files changed, 118 insertions, 39 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp index 9ee2f9f7ea..0125c556cc 100644 --- a/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp +++ b/share/qtcreator/qml/qmlpuppet/container/imagecontainer.cpp @@ -33,18 +33,25 @@ #include <QSharedMemory> #include <QCache> +#define QTC_ASSERT_STRINGIFY_HELPER(x) #x +#define QTC_ASSERT_STRINGIFY(x) QTC_ASSERT_STRINGIFY_HELPER(x) +#define QTC_ASSERT_STRING(cond) qDebug("SOFT ASSERT: \"" cond"\" in file " __FILE__ ", line " QTC_ASSERT_STRINGIFY(__LINE__)) +#define QTC_ASSERT(cond, action) if (cond) {} else { QTC_ASSERT_STRING(#cond); action; } do {} while (0) + namespace QmlDesigner { static QCache<qint32, QSharedMemory> globalSharedMemoryCache(10000); ImageContainer::ImageContainer() - : m_instanceId(-1) + : m_instanceId(-1), + m_keyNumber(-2) { } -ImageContainer::ImageContainer(qint32 instanceId, const QImage &image) +ImageContainer::ImageContainer(qint32 instanceId, const QImage &image, qint32 keyNumber) : m_image(image), - m_instanceId(instanceId) + m_instanceId(instanceId), + m_keyNumber(keyNumber) { } @@ -58,16 +65,46 @@ QImage ImageContainer::image() const return m_image; } +qint32 ImageContainer::keyNumber() const +{ + return m_keyNumber; +} + +void ImageContainer::setImage(const QImage &image) +{ + QTC_ASSERT(m_image.isNull(), /**/); + + m_image = image; +} + +void ImageContainer::removeSharedMemorys(const QVector<qint32> &keyNumberVector) +{ + foreach (qint32 keyNumber, keyNumberVector) { + QSharedMemory *sharedMemory = globalSharedMemoryCache.take(keyNumber); + delete sharedMemory; + } +} + +static const QLatin1String imageKeyTemplateString("Image-%1"); + static QSharedMemory *createSharedMemory(qint32 key, int byteCount) { QSharedMemory *sharedMemory = globalSharedMemoryCache.take(key); + if (sharedMemory == 0) - sharedMemory = new QSharedMemory(QString("Image-%1").arg(key)); + sharedMemory = new QSharedMemory(QString(imageKeyTemplateString).arg(key)); - if (sharedMemory->isAttached()) - sharedMemory->detach(); + bool sharedMemoryIsCreated = sharedMemory->isAttached(); + if (!sharedMemoryIsCreated) + sharedMemoryIsCreated = sharedMemory->attach(); + + bool sharedMemorySizeIsSmallerThanByteCount = sharedMemory->size() < byteCount; + bool sharedMemorySizeIsDoubleBiggerThanByteCount = sharedMemory->size() * 2 > byteCount; - bool sharedMemoryIsCreated = sharedMemory->create(byteCount); + if (!sharedMemoryIsCreated || sharedMemorySizeIsSmallerThanByteCount || sharedMemorySizeIsDoubleBiggerThanByteCount) { + sharedMemory->detach(); + sharedMemoryIsCreated = sharedMemory->create(byteCount); + } if (sharedMemoryIsCreated) { globalSharedMemoryCache.insert(key, sharedMemory); @@ -77,69 +114,111 @@ static QSharedMemory *createSharedMemory(qint32 key, int byteCount) return 0; } -QDataStream &operator<<(QDataStream &out, const ImageContainer &container) +static void writeSharedMemory(QSharedMemory *sharedMemory, const QImage &image) { - out << container.instanceId(); + sharedMemory->lock(); - const QImage image = container.image(); - const QByteArray data(reinterpret_cast<const char*>(image.constBits()), image.byteCount()); + qint32 headerData[5]; + headerData[0] = image.byteCount(); + headerData[1] = image.bytesPerLine(); + headerData[2] = image.size().width(); + headerData[3] = image.size().height(); + headerData[4] = image.format(); + qMemCopy(sharedMemory->data(), headerData, 20); + qMemCopy(reinterpret_cast<char*>(sharedMemory->data()) + 20, image.constBits(), image.byteCount()); + + sharedMemory->unlock(); +} + +static void writeStream(QDataStream &out, const QImage &image) +{ out << qint32(image.bytesPerLine()); out << image.size(); out << qint32(image.format()); out << qint32(image.byteCount()); + out.writeRawData(reinterpret_cast<const char*>(image.constBits()), image.byteCount()); +} - QSharedMemory *sharedMemory = createSharedMemory(container.instanceId(), image.byteCount()); +QDataStream &operator<<(QDataStream &out, const ImageContainer &container) +{ + const int extraDataSize = 20; - out << qint32(sharedMemory != 0); // send if shared memory is used + out << container.instanceId(); + out << container.keyNumber(); - if (sharedMemory) { - sharedMemory->lock(); - qMemCopy(sharedMemory->data(), image.constBits(), image.byteCount()); - sharedMemory->unlock(); - } else { - out.writeRawData(reinterpret_cast<const char*>(image.constBits()), image.byteCount()); - } + const QImage image = container.image(); + QSharedMemory *sharedMemory = createSharedMemory(container.keyNumber(), image.byteCount() + extraDataSize); + out << qint32(sharedMemory != 0); // send if shared memory is used + + if (sharedMemory) + writeSharedMemory(sharedMemory, image); + else + writeStream(out, image); return out; } -void readSharedMemory(qint32 key, QImage *image, qint32 byteSize) +static void readSharedMemory(qint32 key, ImageContainer &container) { - QSharedMemory sharedMemory(QString("Image-%1").arg(key)); + QSharedMemory sharedMemory(QString(imageKeyTemplateString).arg(key)); + bool canAttach = sharedMemory.attach(QSharedMemory::ReadOnly); - if (canAttach) + + if (canAttach && sharedMemory.size() >= 20) { sharedMemory.lock(); - qMemCopy(image->bits(), sharedMemory.constData(), byteSize); + qint32 headerData[5]; + qMemCopy(headerData, sharedMemory.constData(), 20); + + qint32 byteCount = headerData[0]; +// qint32 bytesPerLine = headerData[1]; + qint32 imageWidth = headerData[2]; + qint32 imageHeight = headerData[3]; + qint32 imageFormat = headerData[4]; + + QImage image = QImage(imageWidth, imageHeight, QImage::Format(imageFormat)); + + qMemCopy(image.bits(), reinterpret_cast<const qint32*>(sharedMemory.constData()) + 5, byteCount); + + container.setImage(image); + sharedMemory.unlock(); } } -QDataStream &operator>>(QDataStream &in, ImageContainer &container) +static void readStream(QDataStream &in, ImageContainer &container) { - - qint32 byteSize; + qint32 byteCount; qint32 bytesPerLine; QSize imageSize; - qint32 format; - qint32 sharedmemoryIsUsed; - - in >> container.m_instanceId; + qint32 imageFormat; in >> bytesPerLine; in >> imageSize; - in >> format; - in >> byteSize; - in >> sharedmemoryIsUsed; + in >> imageFormat; + in >> byteCount; - container.m_image = QImage(imageSize, QImage::Format(format)); + QImage image = QImage(imageSize, QImage::Format(imageFormat)); - if (sharedmemoryIsUsed) - readSharedMemory(container.instanceId(), &container.m_image, byteSize); - else - in.readRawData(reinterpret_cast<char*>(container.m_image.bits()), byteSize); + in.readRawData(reinterpret_cast<char*>(image.bits()), byteCount); + + container.setImage(image); +} + +QDataStream &operator>>(QDataStream &in, ImageContainer &container) +{ + qint32 sharedMemoryIsUsed; + + in >> container.m_instanceId; + in >> container.m_keyNumber; + in >> sharedMemoryIsUsed; + + if (sharedMemoryIsUsed) { + readSharedMemory(container.keyNumber(), container); + } else + readStream(in, container); return in; } |