diff options
author | Jonas Karlsson <jonas.karlsson@qt.io> | 2021-02-04 15:37:53 +0100 |
---|---|---|
committer | Jonas Karlsson <jonas.karlsson@qt.io> | 2021-02-09 13:39:47 +0100 |
commit | 2861cfb6f851d7cee503b19f0e800a33374db66c (patch) | |
tree | e5c63255c61568bd327b3851fee2d1b90227c2a4 /src/gui/util | |
parent | d66cb667efbc33b3a81ecc495e90a2e2f44616b2 (diff) |
QTextureFileData: support key value metadata
Task-Id: QTBUG-76970
Pick-to: 6.1
Change-Id: I9dba1b373250cea4d0c806997290a7afcdc900d7
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
Diffstat (limited to 'src/gui/util')
-rw-r--r-- | src/gui/util/qktxhandler.cpp | 41 | ||||
-rw-r--r-- | src/gui/util/qktxhandler_p.h | 3 | ||||
-rw-r--r-- | src/gui/util/qtexturefiledata.cpp | 12 | ||||
-rw-r--r-- | src/gui/util/qtexturefiledata_p.h | 3 |
4 files changed, 56 insertions, 3 deletions
diff --git a/src/gui/util/qktxhandler.cpp b/src/gui/util/qktxhandler.cpp index 27fb69a348..cd8ca3635e 100644 --- a/src/gui/util/qktxhandler.cpp +++ b/src/gui/util/qktxhandler.cpp @@ -146,7 +146,12 @@ QTextureFileData QKtxHandler::read() texData.setNumLevels(decode(header->numberOfMipmapLevels)); texData.setNumFaces(decode(header->numberOfFaces)); - quint32 offset = headerSize + decode(header->bytesOfKeyValueData); + + const quint32 bytesOfKeyValueData = decode(header->bytesOfKeyValueData); + if (headerSize + bytesOfKeyValueData < buf.length()) // oob check + texData.setKeyValueMetadata( + decodeKeyValues(QByteArrayView(buf.data() + headerSize, bytesOfKeyValueData))); + quint32 offset = headerSize + bytesOfKeyValueData; constexpr int MAX_ITERATIONS = 32; // cap iterations in case of corrupt data @@ -213,7 +218,39 @@ bool QKtxHandler::checkHeader(const KTXHeader &header) return is2D && (isCubeMap || isCompressedImage); } -quint32 QKtxHandler::decode(quint32 val) +QMap<QByteArray, QByteArray> QKtxHandler::decodeKeyValues(QByteArrayView view) const +{ + QMap<QByteArray, QByteArray> output; + quint32 offset = 0; + while (offset < view.size() + sizeof(quint32)) { + const quint32 keyAndValueByteSize = + decode(qFromUnaligned<quint32>(view.constData() + offset)); + offset += sizeof(quint32); + + if (offset + keyAndValueByteSize > view.size()) + break; // oob read + + // 'key' is a UTF-8 string ending with a null terminator, 'value' is the rest. + // To separate the key and value we convert the complete data to utf-8 and find the first + // null terminator from the left, here we split the data into two. + const auto str = QString::fromUtf8(view.constData() + offset, keyAndValueByteSize); + const int idx = str.indexOf(QLatin1Char('\0')); + if (idx == -1) + continue; + + const QByteArray key = str.left(idx).toUtf8(); + const size_t keySize = key.size() + 1; // Actual data size + const QByteArray value = QByteArray::fromRawData(view.constData() + offset + keySize, + keyAndValueByteSize - keySize); + + offset = withPadding(offset + keyAndValueByteSize, 4); + output.insert(key, value); + } + + return output; +} + +quint32 QKtxHandler::decode(quint32 val) const { return inverseEndian ? qbswap<quint32>(val) : val; } diff --git a/src/gui/util/qktxhandler_p.h b/src/gui/util/qktxhandler_p.h index 19f7b0e79a..4298433f36 100644 --- a/src/gui/util/qktxhandler_p.h +++ b/src/gui/util/qktxhandler_p.h @@ -68,7 +68,8 @@ public: private: bool checkHeader(const KTXHeader &header); - quint32 decode(quint32 val); + QMap<QByteArray, QByteArray> decodeKeyValues(QByteArrayView view) const; + quint32 decode(quint32 val) const; bool inverseEndian = false; }; diff --git a/src/gui/util/qtexturefiledata.cpp b/src/gui/util/qtexturefiledata.cpp index 0a3958aaf2..6549206a26 100644 --- a/src/gui/util/qtexturefiledata.cpp +++ b/src/gui/util/qtexturefiledata.cpp @@ -100,6 +100,7 @@ public: quint32 baseInternalFormat = 0; int numFaces = 0; int numLevels = 0; + QMap<QByteArray, QByteArray> keyValues; }; QTextureFileData::QTextureFileData() @@ -292,6 +293,17 @@ void QTextureFileData::setLogName(const QByteArray &name) d->logName = name; } +QMap<QByteArray, QByteArray> QTextureFileData::keyValueMetadata() const +{ + return d ? d->keyValues : QMap<QByteArray, QByteArray>(); +} + +void QTextureFileData::setKeyValueMetadata(const QMap<QByteArray, QByteArray> &keyValues) +{ + if (d) + d->keyValues = keyValues; +} + static QByteArray glFormatName(quint32 fmt) { return QByteArray("0x" + QByteArray::number(fmt, 16).rightJustified(4, '0')); diff --git a/src/gui/util/qtexturefiledata_p.h b/src/gui/util/qtexturefiledata_p.h index f6a03c0550..e553733d69 100644 --- a/src/gui/util/qtexturefiledata_p.h +++ b/src/gui/util/qtexturefiledata_p.h @@ -107,6 +107,9 @@ public: QByteArray logName() const; void setLogName(const QByteArray &name); + QMap<QByteArray, QByteArray> keyValueMetadata() const; + void setKeyValueMetadata(const QMap<QByteArray, QByteArray> &keyValues); + private: QSharedDataPointer<QTextureFileDataPrivate> d; }; |