diff options
author | Alex <prevedtest@gmail.com> | 2014-01-15 19:36:44 +0400 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-02-26 09:18:49 +0100 |
commit | d47d38d7d718673e2c3673bb13fa158446ae8fba (patch) | |
tree | db3666b86d6f4bfd92b567f405889957f1456aff | |
parent | 10f883c2dc8264cec87e0e07a0968142216740be (diff) |
Add support for reading icon variants in ICNS plugin
Change-Id: I68395ac4e9604d852405643710aa79585974b3e3
Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com>
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Reviewed-by: Jake Petroules <jake.petroules@petroules.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
-rw-r--r-- | src/plugins/imageformats/icns/qicnshandler.cpp | 39 | ||||
-rw-r--r-- | src/plugins/imageformats/icns/qicnshandler_p.h | 10 | ||||
-rw-r--r-- | tests/auto/icns/tst_qicns.cpp | 1 | ||||
-rw-r--r-- | tests/shared/images/icns.qrc | 1 | ||||
-rw-r--r-- | tests/shared/images/icns/test-variants.icns | bin | 0 -> 16360 bytes |
5 files changed, 47 insertions, 4 deletions
diff --git a/src/plugins/imageformats/icns/qicnshandler.cpp b/src/plugins/imageformats/icns/qicnshandler.cpp index b99c667..c6bff58 100644 --- a/src/plugins/imageformats/icns/qicnshandler.cpp +++ b/src/plugins/imageformats/icns/qicnshandler.cpp @@ -372,7 +372,8 @@ static inline bool isIconCompressed(const ICNSEntry &icon) static inline bool isMaskSuitable(const ICNSEntry &mask, const ICNSEntry &icon, ICNSEntry::Depth target) { - return mask.depth == target && mask.height == icon.height && mask.width == icon.width; + return mask.variant == icon.variant && mask.depth == target + && mask.height == icon.height && mask.width == icon.width; } static inline QByteArray nameFromOSType(quint32 ostype) @@ -813,6 +814,8 @@ QVariant QICNSHandler::option(ImageOption option) const if (option == SubType) { if (imageCount() > 0 && m_currentIconIndex <= imageCount()) { const ICNSEntry &icon = m_icons.at(m_currentIconIndex); + if (icon.variant != 0) + return nameFromOSType(icon.variant) + '-' + nameFromOSType(icon.ostype); return nameFromOSType(icon.ostype); } } @@ -852,11 +855,12 @@ bool QICNSHandler::ensureScanned() const return m_state == ScanSuccess; } -bool QICNSHandler::addEntry(const ICNSBlockHeader &header, qint64 imgDataOffset) +bool QICNSHandler::addEntry(const ICNSBlockHeader &header, qint64 imgDataOffset, quint32 variant) { // Note: This function returns false only when a device positioning error occurred ICNSEntry entry; entry.ostype = header.ostype; + entry.variant = variant; entry.dataOffset = imgDataOffset; entry.dataLength = header.length - ICNSBlockHeaderSize; // Check for known magic numbers: @@ -920,6 +924,37 @@ bool QICNSHandler::scanDevice() // We don't have a good use for these blocks... yet. stream.skipRawData(blockDataLength); break; + case ICNSBlockHeader::TypeTile: + case ICNSBlockHeader::TypeOver: + case ICNSBlockHeader::TypeOpen: + case ICNSBlockHeader::TypeDrop: + case ICNSBlockHeader::TypeOdrp: + // Icns container seems to have an embedded icon variant container + // Let's start a scan for entries + while (device()->pos() < nextBlockOffset) { + ICNSBlockHeader icon; + stream >> icon; + // Check for incorrect variant entry header and stop scan + if (!isBlockHeaderValid(icon, blockDataLength)) + break; + if (!addEntry(icon, device()->pos(), blockHeader.ostype)) + return false; + if (stream.skipRawData(icon.length - ICNSBlockHeaderSize) < 0) + return false; + } + if (device()->pos() != nextBlockOffset) { + // Scan of this container didn't end where we expected. + // Let's generate some output about this incident: + qWarning("Scan of the icon variant container (\"%s\") failed at pos %s.\n" \ + "Reason: Scan didn't reach the end of this container's block, " \ + "delta: %s bytes. This file may be corrupted.", + nameFromOSType(blockHeader.ostype).constData(), + QByteArray::number(device()->pos()).constData(), + QByteArray::number(nextBlockOffset - device()->pos()).constData()); + if (!device()->seek(nextBlockOffset)) + return false; + } + break; case ICNSBlockHeader::TypeToc: { // Quick scan, table of contents if (blockDataOffset != ICNSBlockHeaderSize * 2) { diff --git a/src/plugins/imageformats/icns/qicnshandler_p.h b/src/plugins/imageformats/icns/qicnshandler_p.h index 12c165b..747cb3e 100644 --- a/src/plugins/imageformats/icns/qicnshandler_p.h +++ b/src/plugins/imageformats/icns/qicnshandler_p.h @@ -60,6 +60,11 @@ struct ICNSBlockHeader TypeIcnv = MAKEOSTYPE('i', 'c', 'n', 'V'), // Icon Composer version // Legacy: TypeClut = MAKEOSTYPE('c', 'l', 'u', 't'), // Color look-up table (pre-OS X resources) + TypeTile = MAKEOSTYPE('t', 'i', 'l', 'e'), // Container (icon variants) + TypeOver = MAKEOSTYPE('o', 'v', 'e', 'r'), // Container (icon variants) + TypeOpen = MAKEOSTYPE('o', 'p', 'e', 'n'), // Container (icon variants) + TypeDrop = MAKEOSTYPE('d', 'r', 'o', 'p'), // Container (icon variants) + TypeOdrp = MAKEOSTYPE('o', 'd', 'r', 'p'), // Container (icon variants) }; quint32 ostype; @@ -102,6 +107,7 @@ struct ICNSEntry }; quint32 ostype; // Real OSType + quint32 variant; // Virtual OSType: a parent container, zero if parent is icns root Group group; // ASCII character number quint32 width; // For uncompressed icons only, zero for compressed ones for now quint32 height; // For uncompressed icons only, zero for compressed ones fow now @@ -112,7 +118,7 @@ struct ICNSEntry qint64 dataOffset; // Offset from the initial position of the file/device ICNSEntry() : - ostype(0), group(GroupUnknown), width(0), height(0), depth(DepthUnknown), + ostype(0), variant(0), group(GroupUnknown), width(0), height(0), depth(DepthUnknown), flags(Unknown), dataFormat(FormatUnknown), dataLength(0), dataOffset(0) { } @@ -142,7 +148,7 @@ public: private: bool ensureScanned() const; bool scanDevice(); - bool addEntry(const ICNSBlockHeader &header, qint64 imgDataOffset); + bool addEntry(const ICNSBlockHeader &header, qint64 imgDataOffset, quint32 variant = 0); const ICNSEntry &getIconMask(const ICNSEntry &icon) const; private: diff --git a/tests/auto/icns/tst_qicns.cpp b/tests/auto/icns/tst_qicns.cpp index 261590e..29ca3ee 100644 --- a/tests/auto/icns/tst_qicns.cpp +++ b/tests/auto/icns/tst_qicns.cpp @@ -65,6 +65,7 @@ void tst_qicns::readIcons_data() QTest::newRow("2") << QStringLiteral("test-jp2") << QSize(128, 128) << 7 << QByteArrayLiteral("jp2"); QTest::newRow("3") << QStringLiteral("test-32bit") << QSize(128, 128) << 4 << QByteArray(); QTest::newRow("4") << QStringLiteral("test-legacy") << QSize(48, 48) << 12 << QByteArray(); + QTest::newRow("5") << QStringLiteral("test-variants") << QSize(128, 128) << 5 << QByteArrayLiteral("png"); } void tst_qicns::readIcons() diff --git a/tests/shared/images/icns.qrc b/tests/shared/images/icns.qrc index 072b78c..f87830d 100644 --- a/tests/shared/images/icns.qrc +++ b/tests/shared/images/icns.qrc @@ -4,6 +4,7 @@ <file>icns/test-jp2.icns</file> <file>icns/test-32bit.icns</file> <file>icns/test-legacy.icns</file> + <file>icns/test-variants.icns</file> <file>icns/test-write-16.png</file> <file>icns/test-write-32.png</file> <file>icns/test-write-64.png</file> diff --git a/tests/shared/images/icns/test-variants.icns b/tests/shared/images/icns/test-variants.icns Binary files differnew file mode 100644 index 0000000..e623279 --- /dev/null +++ b/tests/shared/images/icns/test-variants.icns |