File indexing completed on 2025-01-05 04:01:13
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 #pragma once 0007 0008 #include <QDomDocument> 0009 #include "aep_riff.hpp" 0010 #include "io/svg/detail.hpp" 0011 0012 namespace glaxnimate::io::aep { 0013 0014 class AepxConverter 0015 { 0016 public: 0017 0018 RiffChunk aepx_to_chunk(const QDomElement& element) 0019 { 0020 QString header = element.tagName(); 0021 0022 if ( header == "ProjectXMPMetadata" ) 0023 { 0024 return chunk("XMPM", text(element.text())); 0025 } 0026 else if ( header == "string" ) 0027 { 0028 return chunk("Utf8", text(element.text())); 0029 } 0030 else if ( header == "numS" ) 0031 { 0032 std::uint32_t val = element.firstChildElement().text().toUInt(); 0033 auto data = buffer(Endianness::Big().write_uint(val)); 0034 return chunk(header, data); 0035 } 0036 else if ( header == "ppSn" ) 0037 { 0038 std::uint32_t val = element.firstChildElement().text().toDouble(); 0039 auto data = buffer(Endianness::Big().write_float64(val)); 0040 return chunk(header, data); 0041 } 0042 else if ( element.hasAttribute("bdata") ) 0043 { 0044 return chunk(header, hex(element.attribute("bdata"))); 0045 } 0046 0047 ChunkId riff_header = header.toLatin1(); 0048 ChunkId subheader = {""}; 0049 if ( header == "AfterEffectsProject" ) 0050 { 0051 riff_header = {"RIFX"}; 0052 } 0053 else if ( !AepRiff::is_fake_list(riff_header) ) 0054 { 0055 subheader = riff_header; 0056 riff_header = {"LIST"}; 0057 } 0058 0059 return {riff_header, 0, subheader, {}, read_chunk_list(svg::detail::ElementRange(element))}; 0060 } 0061 0062 std::vector<std::unique_ptr<RiffChunk>> read_chunk_list(const svg::detail::ElementRange& range) 0063 { 0064 std::vector<std::unique_ptr<RiffChunk>> out; 0065 out.reserve(range.size()); 0066 for ( const auto& el : range ) 0067 out.push_back(std::make_unique<RiffChunk>(aepx_to_chunk(el))); 0068 return out; 0069 } 0070 0071 private: 0072 struct BinaryData 0073 { 0074 QByteArray data; 0075 QBuffer file; 0076 std::uint32_t length; 0077 }; 0078 0079 RiffChunk chunk(const QString& header, BinaryData* data, const QString& subheader = {}) 0080 { 0081 return { 0082 header.toLatin1(), data->length, subheader.toLatin1(), 0083 {Endianness::Big(), &data->file, data->length, 0} 0084 }; 0085 } 0086 0087 BinaryData* buffer(QByteArray&& content) 0088 { 0089 data.push_back(std::make_unique<BinaryData>()); 0090 data.back()->length = content.size(); 0091 data.back()->data = std::move(content); 0092 data.back()->file.setBuffer(&data.back()->data); 0093 data.back()->file.open(QIODevice::ReadOnly); 0094 return data.back().get(); 0095 } 0096 0097 BinaryData* hex(const QString& hex) 0098 { 0099 return buffer(QByteArray::fromHex(hex.toLatin1())); 0100 } 0101 0102 BinaryData* text(const QString& string) 0103 { 0104 return buffer(string.toUtf8()); 0105 } 0106 0107 std::vector<std::unique_ptr<BinaryData>> data; 0108 }; 0109 0110 } // namespace glaxnimate::io::aep