diff --git a/Pdf4QtLib/sources/pdf3d_u3d.cpp b/Pdf4QtLib/sources/pdf3d_u3d.cpp index af8b4db..423477b 100644 --- a/Pdf4QtLib/sources/pdf3d_u3d.cpp +++ b/Pdf4QtLib/sources/pdf3d_u3d.cpp @@ -588,39 +588,10 @@ const PDF3D_U3D_ContextManager::ContextData* PDF3D_U3D_ContextManager::getContex PDF3D_U3D::PDF3D_U3D() { - // Jakub Melka: 106 is default value for U3D strings - m_textCodec = QTextCodec::codecForMib(106); + } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlockWithDeclaration(PDF3D_U3D_DataReader& reader) -{ - uint32_t blockType = reader.readU32(); - uint32_t dataSize = reader.readU32(); - uint32_t metaDataSize = reader.readU32(); - - // Read block data - QByteArray blockData = reader.readByteArray(dataSize); - reader.skipBytes(getBlockPadding(dataSize)); - - // Read block metadata - QByteArray metaData = reader.readByteArray(metaDataSize); - reader.skipBytes(getBlockPadding(metaDataSize)); - - auto block = parseBlock(blockType, blockData, metaData); - - LoadBlockInfo info; - info.typeName = QByteArray::fromRawData(reinterpret_cast(&blockType), sizeof(decltype(blockType))).toHex(); - info.success = block != nullptr; - info.blockType = blockType; - info.dataSize = dataSize; - info.metaDataSize = metaDataSize; - info.block = block; - m_allBlocks.push_back(info); - - return block; -} - -PDF3D_U3D_Block_Data PDF3D_U3D::readBlockData(PDF3D_U3D_DataReader& reader) +PDF3D_U3D_Block_Data PDF3D_U3D_Parser::readBlockData(PDF3D_U3D_DataReader& reader) { PDF3D_U3D_Block_Data data; @@ -639,59 +610,51 @@ PDF3D_U3D_Block_Data PDF3D_U3D::readBlockData(PDF3D_U3D_DataReader& reader) QByteArray metaData = reader.readByteArray(metaDataSize); reader.skipBytes(getBlockPadding(metaDataSize)); - data.blockType = blockType; + data.blockType = static_cast(blockType); data.blockData = std::move(blockData); data.metaData = std::move(metaData); return data; } -PDF3D_U3D PDF3D_U3D::parse(QByteArray data) +PDF3D_U3D_Parser::PDF3D_U3D_Parser() { - PDF3D_U3D object; + // Jakub Melka: 106 is default value for U3D strings + m_textCodec = QTextCodec::codecForMib(106); +} - // Why to use shared ptr and weak ptr in the object? - // In case exception is thrown in the parser, context - // manager will be automatically released. - std::shared_ptr contextManager = std::make_shared(); - object.setContextManager(contextManager); - PDF3D_U3D_DataReader reader(data, true, contextManager.get()); - - object.m_priority = 0; - - QStringList errors; - PDF3D_U3D_DecoderLists decoderLists; +PDF3D_U3D PDF3D_U3D_Parser::parse(QByteArray data) +{ + PDF3D_U3D_DataReader reader(data, true, &m_contextManager); + m_priority = 0; while (!reader.isAtEnd()) { PDF3D_U3D_Block_Data blockData = readBlockData(reader); - processBlock(blockData, decoderLists, errors); + processBlock(blockData, PDF3D_U3D_Block_Info::PL_LastPalette); } - return object; + return m_object; } -void PDF3D_U3D::processBlock(PDF3D_U3D& object, - const PDF3D_U3D_Block_Data& blockData, - PDF3D_U3D_DecoderLists& decoderLists, - QStringList& errors, - PDF3D_U3D_DecoderLists::EPalette palette) +void PDF3D_U3D_Parser::processBlock(const PDF3D_U3D_Block_Data& blockData, + PDF3D_U3D_Block_Info::EPalette palette) { switch (blockData.blockType) { case PDF3D_U3D_FileBlock::ID: { // Parse file block - object.m_fileBlock = object.parseBlock(blockData); + m_fileBlock = parseBlock(blockData); break; } case PDF3D_U3D_PriorityUpdateBlock::ID: { // Parse priority update block - auto block = object.parseBlock(blockData); + auto block = parseBlock(blockData); const PDF3D_U3D_PriorityUpdateBlock* priorityUpdateBlock = dynamic_cast(block.get()); - object.m_priority = priorityUpdateBlock->getNewPriority(); + m_priority = priorityUpdateBlock->getNewPriority(); break; } @@ -699,87 +662,115 @@ void PDF3D_U3D::processBlock(PDF3D_U3D& object, case PDF3D_U3D_FileReferenceBlock::ID: // Skip this block, we do not handle these type of blocks, // just read it... to check errors. - object.parseBlock(blockData); + parseBlock(blockData); break; case PDF3D_U3D_ModifierChainBlock::ID: - { - // Add decoder list for modifier chain block - auto block = object.parseBlock(blockData); - const PDF3D_U3D_ModifierChainBlock* chainBlock = dynamic_cast(block.get()); - - PDF3D_U3D_DecoderList decoderList; - decoderList.setName(chainBlock->getModifierChainName()); - - for (const auto& block : chainBlock->getModifierDeclarationBlocks()) - { - decoderList.createChain(block); - } - - decoderLists.addDecoderList(std::move(decoderList)); + processModifierBlock(blockData); break; - } default: - { - PDF3D_U3D_DataReader blockReader(blockData.blockData, object.isCompressed(), object.getContextManager()); - QString blockName = blockReader.readString(object.getTextCodec()); - - if (isContinuationBlock(blockData.blockType)) - { - uint32_t chainIndex = 0; - if (blockData.blockType != 0xFFFFFF5C) - { - chainIndex = blockReader.readU32(); - } - - if (!decoderLists.addContinuationBlock(blockName, chainIndex, blockData)) - { - errors << QString("Failed to add continuation block '%1'").arg(blockName); - } - } - else - { - PDF3D_U3D_DecoderList decoderList; - decoderList.createChain(blockData); - decoderLists.addDecoderList(std::move(decoderList)); - } - + processGenericBlock(blockData, palette); break; - } } } -template -const T* PDF3D_U3D::getBlock(const QString& name) const +void PDF3D_U3D_Parser::processModifierBlock(const PDF3D_U3D_Block_Data& blockData) { - for (const auto& block : m_allBlocks) + // Add decoder list for modifier chain block + auto block = parseBlock(blockData); + const PDF3D_U3D_ModifierChainBlock* chainBlock = dynamic_cast(block.get()); + + PDF3D_U3D_Block_Info::EPalette palette = PDF3D_U3D_Block_Info::PL_LastPalette; + switch (chainBlock->getModifierChainType()) { - if (auto typedBlock = dynamic_cast(block.block.data())) - { - if (typedBlock->getName() == name) - { - return typedBlock; - } - } + case 0: + palette = PDF3D_U3D_Block_Info::PL_Node; + break; + + case 1: + palette = PDF3D_U3D_Block_Info::PL_Generator; + break; + + case 2: + palette = PDF3D_U3D_Block_Info::PL_Texture; + break; + + default: + return; } - return nullptr; + for (const auto& block : chainBlock->getModifierDeclarationBlocks()) + { + processBlock(block, palette); + } +} + +void PDF3D_U3D_Parser::processGenericBlock(const PDF3D_U3D_Block_Data& blockData, + PDF3D_U3D_Block_Info::EPalette palette) +{ + PDF3D_U3D_DataReader blockReader(blockData.blockData, isCompressed(), getContextManager()); + QString blockName = blockReader.readString(getTextCodec()); + + uint32_t chainIndex = 0; + PDF3D_U3D_Block_Info::EPalette effectivePalette = PDF3D_U3D_Block_Info::isChain(blockData.blockType) ? palette + : PDF3D_U3D_Block_Info::getPalette(blockData.blockType); + + PDF3D_U3D_DecoderPalette* decoderPalette = m_decoderLists.getDecoderPalette(effectivePalette); + + if (PDF3D_U3D_Block_Info::isContinuation(blockData.blockType)) + { + if (blockData.blockType != PDF3D_U3D_Block_Info::BT_ResourceTextureCont) + { + chainIndex = blockReader.readU32(); + } + + PDF3D_U3D_DecoderChain* decoderChain = decoderPalette->getDecoderChain(blockName); + if (!decoderChain) + { + m_errors << QString("Failed to add continuation block '%1' - decoder chain does not exist!").arg(blockName); + return; + } + + PDF3D_U3D_Decoder* decoder = decoderChain->getDecoder(chainIndex); + if (!decoder) + { + m_errors << QString("Failed to add continuation block '%1' - decoder does not exist at position %2!").arg(blockName).arg(chainIndex); + return; + } + + decoder->addBlock(blockData); + } + else + { + PDF3D_U3D_Decoder decoder; + decoder.addBlock(blockData); + + PDF3D_U3D_DecoderChain* decoderChain = decoderPalette->getDecoderChain(blockName); + if (!decoderChain) + { + decoderChain = decoderPalette->createDecoderChain(blockName); + } + + decoderChain->addDecoder(std::move(decoder)); + } } const PDF3D_U3D_CLODMeshDeclarationBlock* PDF3D_U3D::getCLODMeshDeclarationBlock(const QString& meshName) const { - return getBlock(meshName); + // TODO: Opravit + return nullptr; //getBlock(meshName); } const PDF3D_U3D_LineSetDeclarationBlock* PDF3D_U3D::getLineSetDeclarationBlock(const QString& lineSetName) const { - return getBlock(lineSetName); + // TODO: Opravit + return nullptr; //getBlock(lineSetName); } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(uint32_t blockType, - const QByteArray& data, - const QByteArray& metaData) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_Parser::parseBlock(uint32_t blockType, + const QByteArray& data, + const QByteArray& metaData) { switch (blockType) { @@ -851,12 +842,12 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(uint32_t blockType, return PDF3D_U3D_AbstractBlockPtr(); } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D::parseBlock(const PDF3D_U3D_Block_Data& data) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_Parser::parseBlock(const PDF3D_U3D_Block_Data& data) { return parseBlock(data.blockType, data.blockData, data.metaData); } -uint32_t PDF3D_U3D::getBlockPadding(uint32_t blockSize) +uint32_t PDF3D_U3D_Parser::getBlockPadding(uint32_t blockSize) { uint32_t extraBytes = blockSize % 4; @@ -868,25 +859,7 @@ uint32_t PDF3D_U3D::getBlockPadding(uint32_t blockSize) return 0; } -bool PDF3D_U3D::isContinuationBlock(uint32_t blockType) -{ - switch (blockType) - { - case 0xFFFFFF3B: - case 0xFFFFFF3C: - case 0xFFFFFF3E: - case 0xFFFFFF3F: - case 0xFFFFFF5C: - return true; - - default: - break; - } - - return false; -} - -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_FileBlock* block = new PDF3D_U3D_FileBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -946,7 +919,7 @@ PDFReal PDF3D_U3D_FileBlock::getUnitScalingFactor() const return m_unitScalingFactor; } -void PDF3D_U3D_AbstractBlock::parseMetadata(QByteArray metaData, PDF3D_U3D* object) +void PDF3D_U3D_AbstractBlock::parseMetadata(QByteArray metaData, PDF3D_U3D_Parser* object) { if (metaData.isEmpty()) { @@ -976,7 +949,7 @@ void PDF3D_U3D_AbstractBlock::parseMetadata(QByteArray metaData, PDF3D_U3D* obje } } -PDF3D_U3D_AbstractBlock::ParentNodesData PDF3D_U3D_AbstractBlock::parseParentNodeData(PDF3D_U3D_DataReader& reader, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlock::ParentNodesData PDF3D_U3D_AbstractBlock::parseParentNodeData(PDF3D_U3D_DataReader& reader, PDF3D_U3D_Parser* object) { ParentNodesData result; @@ -999,7 +972,7 @@ PDF3D_U3D_AbstractBlock::ParentNodesData PDF3D_U3D_AbstractBlock::parseParentNod return result; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileReferenceBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_FileReferenceBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_FileReferenceBlock* block = new PDF3D_U3D_FileReferenceBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1101,7 +1074,7 @@ const QString& PDF3D_U3D_FileReferenceBlock::getWorldAliasName() const return m_worldAliasName; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModifierChainBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModifierChainBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_ModifierChainBlock* block = new PDF3D_U3D_ModifierChainBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1168,7 +1141,7 @@ const std::vector& PDF3D_U3D_ModifierChainBlock::getModifi return m_modifierDeclarationBlocks; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_PriorityUpdateBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_PriorityUpdateBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_PriorityUpdateBlock* block = new PDF3D_U3D_PriorityUpdateBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1187,7 +1160,7 @@ uint32_t PDF3D_U3D_PriorityUpdateBlock::getNewPriority() const return m_newPriority; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectTypeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectTypeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_NewObjectTypeBlock* block = new PDF3D_U3D_NewObjectTypeBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1265,7 +1238,7 @@ const QString& PDF3D_U3D_NewObjectTypeBlock::getExtensionInformationString() con return m_extensionInformationString; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_NewObjectBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_NewObjectBlock* block = new PDF3D_U3D_NewObjectBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1296,7 +1269,7 @@ const QByteArray& PDF3D_U3D_NewObjectBlock::getData() const return m_data; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_GroupNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_GroupNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_GroupNodeBlock* block = new PDF3D_U3D_GroupNodeBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1321,7 +1294,7 @@ const PDF3D_U3D_GroupNodeBlock::ParentNodesData& PDF3D_U3D_GroupNodeBlock::getPa return m_parentNodesData; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModelNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ModelNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_ModelNodeBlock* block = new PDF3D_U3D_ModelNodeBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1358,7 +1331,7 @@ uint32_t PDF3D_U3D_ModelNodeBlock::getModelVisibility() const return m_modelVisibility; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LightNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LightNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_LightNodeBlock* block = new PDF3D_U3D_LightNodeBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1389,7 +1362,7 @@ const QString& PDF3D_U3D_LightNodeBlock::getLightResourceName() const return m_lightResourceName; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ViewNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_ViewNodeBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_ViewNodeBlock* block = new PDF3D_U3D_ViewNodeBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1535,7 +1508,7 @@ const std::vector& PDF3D_U3D_ViewNodeBlock return m_overlay; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODMeshDeclarationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODMeshDeclarationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_CLODMeshDeclarationBlock* block = new PDF3D_U3D_CLODMeshDeclarationBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1744,7 +1717,7 @@ const std::vector& PDF3D_U3 return m_boneDescription; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODBaseMeshContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODBaseMeshContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_CLODBaseMeshContinuationBlock* block = new PDF3D_U3D_CLODBaseMeshContinuationBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1769,8 +1742,9 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODBaseMeshContinuationBlock::parse(QByteA block->m_baseSpecularColors = reader.readVectorFloats32(block->m_specularColorCount); block->m_baseTextureCoords = reader.readVectorFloats32(block->m_textureColorCount); + // TODO: Fix this // We must read attributes of the mesh to read faces - if (auto declarationBlock = object->getCLODMeshDeclarationBlock(block->m_meshName)) + /*if (auto declarationBlock = object->getCLODMeshDeclarationBlock(block->m_meshName)) { const bool hasNormals = !declarationBlock->isNormalsExcluded(); @@ -1816,7 +1790,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODBaseMeshContinuationBlock::parse(QByteA block->m_baseFaces.emplace_back(std::move(face)); } - } + }*/ block->parseMetadata(metaData, object); return pointer; @@ -1882,7 +1856,7 @@ const std::vector& PDF3D_U3D_ return m_baseFaces; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_CLODProgressiveMeshContinuationBlock* block = new PDF3D_U3D_CLODProgressiveMeshContinuationBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -1981,7 +1955,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_CLODProgressiveMeshContinuationBlock::parse return pointer; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetDeclarationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetDeclarationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_LineSetDeclarationBlock* block = new PDF3D_U3D_LineSetDeclarationBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -2094,7 +2068,7 @@ float PDF3D_U3D_LineSetDeclarationBlock::getSpecularColorInverseQuant() const return m_specularColorInverseQuant; } -PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object) +PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object) { PDF3D_U3D_LineSetContinuationBlock* block = new PDF3D_U3D_LineSetContinuationBlock(); PDF3D_U3D_AbstractBlockPtr pointer(block); @@ -2108,7 +2082,8 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray block->m_startResolution = reader.readU32(); block->m_endResolution = reader.readU32(); - if (auto declarationBlock = object->getLineSetDeclarationBlock(block->m_lineSetName)) + // TODO: Fix this + /*if (auto declarationBlock = object->getLineSetDeclarationBlock(block->m_lineSetName)) { for (uint32_t i = block->m_startResolution; i < block->m_endResolution; ++i) { @@ -2210,7 +2185,7 @@ PDF3D_U3D_AbstractBlockPtr PDF3D_U3D_LineSetContinuationBlock::parse(QByteArray else { return nullptr; - } + }*/ block->parseMetadata(metaData, object); return pointer; @@ -2221,70 +2196,147 @@ const std::vector& PDF3D_U3D_Lin return m_updateItems; } -const QString& PDF3D_U3D_DecoderList::getName() const + +PDF3D_U3D_DecoderPalette* PDF3D_U3D_DecoderPalettes::getDecoderPalette(EPalette palette) { - return m_name; + Q_ASSERT(palette < m_decoderLists.size()); + return &m_decoderLists[palette]; } -void PDF3D_U3D_DecoderList::setName(const QString& newName) +constexpr bool PDF3D_U3D_Block_Info::isChain(EBlockType blockType) { - m_name = newName; -} - -const std::vector& PDF3D_U3D_DecoderList::getChains() const -{ - return m_chains; -} - -void PDF3D_U3D_DecoderList::setChains(const std::vector& newChains) -{ - m_chains = newChains; -} - -PDF3D_U3D_DecorderList_ChainItem* PDF3D_U3D_DecoderList::getChain(size_t index) -{ - if (index < m_chains.size()) + switch (blockType) { - return &m_chains[index]; - } - - return nullptr; -} - -void PDF3D_U3D_DecoderList::createChain(const PDF3D_U3D_Block_Data& data) -{ - PDF3D_U3D_DecorderList_ChainItem item; - item.blocks = { data }; - m_chains.emplace_back(std::move(item)); -} - -PDF3D_U3D_DecoderList* PDF3D_U3D_DecoderLists::getDecoderList(QString name) -{ - for (PDF3D_U3D_DecoderList& decoderList : m_decoderLists) - { - if (decoderList.getName() == name) - { - return &decoderList; - } - } - - return nullptr; -} - -bool PDF3D_U3D_DecoderLists::addContinuationBlock(QString name, uint32_t chainIndex, const PDF3D_U3D_Block_Data& data) -{ - if (PDF3D_U3D_DecoderList* decoderList = getDecoderList(name)) - { - if (PDF3D_U3D_DecorderList_ChainItem* chain = decoderList->getChain(chainIndex)) - { - chain->blocks.push_back(data); + case BT_Modifier2DGlyph: + case BT_ModifierSubdivision: + case BT_ModifierAnimation: + case BT_ModifierBoneWeights: + case BT_ModifierShading: + case BT_ModifierCLOD: return true; - } + + default: + return false; + } +} + +constexpr bool PDF3D_U3D_Block_Info::isContinuation(EBlockType blockType) +{ + switch (blockType) + { + case BT_GeneratorCLODBaseMesh: + case BT_GeneratorCLODProgMesh: + case BT_GeneratorPointSetCont: + case BT_GeneratorLineSetCont: + case BT_ResourceTextureCont: + return true; + + default: + break; } return false; } +PDF3D_U3D_Block_Info::EPalette PDF3D_U3D_Block_Info::getPalette(EBlockType blockType) +{ + switch (blockType) + { + case BT_Unknown: + Q_ASSERT(false); + break; + + case BT_FileHeader: + case BT_FileReference: + case BT_FileModifierChain: + case BT_FilePriorityUpdate: + case BT_FileNewObject: + Q_ASSERT(false); // Do not have a palette + break; + + case BT_NodeGroup: + case BT_NodeModel: + case BT_NodeLight: + case BT_NodeView: + return PL_Node; + + case BT_GeneratorCLODMeshDecl: + case BT_GeneratorCLODBaseMesh: + case BT_GeneratorCLODProgMesh: + case BT_GeneratorPointSet: + case BT_GeneratorPointSetCont: + case BT_GeneratorLineSet: + case BT_GeneratorLineSetCont: + return PL_Generator; + + case BT_Modifier2DGlyph: + case BT_ModifierSubdivision: + case BT_ModifierAnimation: + case BT_ModifierBoneWeights: + case BT_ModifierShading: + case BT_ModifierCLOD: + return PL_Node; + + case BT_ResourceLight: + return PL_Light; + + case BT_ResourceView: + return PL_View; + + case BT_ResourceLitShader: + return PL_Shader; + + case BT_ResourceMaterial: + return PL_Material; + + case BT_ResourceTexture: + case BT_ResourceTextureCont: + return PL_Texture; + + case BT_ResourceMotion: + return PL_Motion; + } + + return PL_LastPalette; +} + +const QString& PDF3D_U3D_DecoderChain::getName() const +{ + return m_name; +} + +void PDF3D_U3D_DecoderChain::setName(const QString& newName) +{ + m_name = newName; +} + +PDF3D_U3D_Decoder* PDF3D_U3D_DecoderChain::getDecoder(uint32_t chainPosition) +{ + return (chainPosition < m_decoders.size()) ? &m_decoders[chainPosition] : nullptr; +} + +PDF3D_U3D_DecoderChain* PDF3D_U3D_DecoderPalette::getDecoderChain(const QString& name) +{ + for (auto& decoderChain : m_decoderChains) + { + if (decoderChain.getName() == name) + { + return &decoderChain; + } + } + + return nullptr; +} + +PDF3D_U3D_DecoderChain* PDF3D_U3D_DecoderPalette::createDecoderChain(const QString& name) +{ + Q_ASSERT(!getDecoderChain(name)); + + m_decoderChains.emplace_back(); + m_decoderChains.back().setName(name); + return &m_decoderChains.back(); +} + } // namespace u3d } // namespace pdf diff --git a/Pdf4QtLib/sources/pdf3d_u3d.h b/Pdf4QtLib/sources/pdf3d_u3d.h index dc35caf..d7798c7 100644 --- a/Pdf4QtLib/sources/pdf3d_u3d.h +++ b/Pdf4QtLib/sources/pdf3d_u3d.h @@ -74,6 +74,7 @@ enum Context }; class PDF3D_U3D; +class PDF3D_U3D_Parser; class PDF3D_U3D_DataReader; class PDF3D_U3D_ContextManager; @@ -102,9 +103,67 @@ struct PDF3D_U3D_QuantizedVec3 uint32_t diff3; }; +struct PDF3D_U3D_Block_Info +{ + enum EBlockType : uint32_t + { + BT_Unknown = 0x00000000, + BT_FileHeader = 0x00443355, + BT_FileReference = 0xFFFFFF12, + BT_FileModifierChain = 0xFFFFFF14, + BT_FilePriorityUpdate = 0xFFFFFF15, + BT_FileNewObject = 0xFFFFFF16, + + BT_NodeGroup = 0xFFFFFF21, + BT_NodeModel = 0xFFFFFF22, + BT_NodeLight = 0xFFFFFF23, + BT_NodeView = 0xFFFFFF24, + + BT_GeneratorCLODMeshDecl = 0xFFFFFF31, + BT_GeneratorCLODBaseMesh = 0xFFFFFF3B, + BT_GeneratorCLODProgMesh = 0xFFFFFF3C, + BT_GeneratorPointSet = 0xFFFFFF36, + BT_GeneratorPointSetCont = 0xFFFFFF3E, + BT_GeneratorLineSet = 0xFFFFFF37, + BT_GeneratorLineSetCont = 0xFFFFFF3F, + + BT_Modifier2DGlyph = 0xFFFFFF41, + BT_ModifierSubdivision = 0xFFFFFF42, + BT_ModifierAnimation = 0xFFFFFF43, + BT_ModifierBoneWeights = 0xFFFFFF44, + BT_ModifierShading = 0xFFFFFF45, + BT_ModifierCLOD = 0xFFFFFF46, + + BT_ResourceLight = 0xFFFFFF51, + BT_ResourceView = 0xFFFFFF52, + BT_ResourceLitShader = 0xFFFFFF53, + BT_ResourceMaterial = 0xFFFFFF54, + BT_ResourceTexture = 0xFFFFFF55, + BT_ResourceTextureCont = 0xFFFFFF5C, + BT_ResourceMotion = 0xFFFFFF56 + }; + + enum EPalette + { + PL_Material, + PL_Generator, + PL_Shader, + PL_Texture, + PL_Motion, + PL_Node, + PL_View, + PL_Light, + PL_LastPalette + }; + + static constexpr bool isChain(EBlockType blockType); + static constexpr bool isContinuation(EBlockType blockType); + static EPalette getPalette(EBlockType blockType); +}; + struct PDF3D_U3D_Block_Data { - uint32_t blockType = 0; + PDF3D_U3D_Block_Info::EBlockType blockType = PDF3D_U3D_Block_Info::EBlockType(); QByteArray blockData; QByteArray metaData; @@ -127,7 +186,7 @@ public: inline constexpr PDF3D_U3D_AbstractBlock() = default; virtual ~PDF3D_U3D_AbstractBlock() = default; - void parseMetadata(QByteArray metaData, PDF3D_U3D* object); + void parseMetadata(QByteArray metaData, PDF3D_U3D_Parser* object); struct ParentNodeData { @@ -145,7 +204,7 @@ public: QByteArray binaryData; }; - static ParentNodesData parseParentNodeData(PDF3D_U3D_DataReader& reader, PDF3D_U3D* object); + static ParentNodesData parseParentNodeData(PDF3D_U3D_DataReader& reader, PDF3D_U3D_Parser* object); private: std::vector m_metaData; @@ -166,7 +225,7 @@ class PDF3D_U3D_FileBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0x00443355; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); bool isExtensibleProfile() const { return m_profileIdentifier & 0x00000002; } bool isNoCompressionMode() const { return m_profileIdentifier & 0x00000004; } @@ -198,7 +257,7 @@ public: bool isBoundingSpherePresent() const { return m_fileReferenceAttributes & 0x00000001; } bool isAxisAlignedBoundingBoxPresent() const { return m_fileReferenceAttributes & 0x00000002; } - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct Filter { @@ -236,7 +295,7 @@ class PDF3D_U3D_ModifierChainBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF14; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); bool isBoundingSpherePresent() const { return m_modifierChainAttributes & 0x00000001; } bool isAxisAlignedBoundingBoxPresent() const { return m_modifierChainAttributes & 0x00000002; } @@ -269,7 +328,7 @@ class PDF3D_U3D_PriorityUpdateBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF15; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); uint32_t getNewPriority() const; @@ -282,7 +341,7 @@ class PDF3D_U3D_NewObjectTypeBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF16; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); const QString& getNewObjectTypeName() const; uint32_t getModifierType() const; @@ -314,7 +373,7 @@ public: static constexpr uint32_t ID_MIN = 0x00000100; static constexpr uint32_t ID_MAX = 0x00FFFFFF; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); const QString& getObjectName() const; uint32_t getChainIndex() const; @@ -335,7 +394,7 @@ class PDF3D_U3D_GroupNodeBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF21; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); const QString& getGroupNodeName() const; const ParentNodesData& getParentNodesData() const; @@ -350,7 +409,7 @@ class PDF3D_U3D_ModelNodeBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF22; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); bool isHidden() const { return m_modelVisibility == 0; } bool isFrontVisible() const { return m_modelVisibility == 1; } @@ -374,7 +433,7 @@ class PDF3D_U3D_LightNodeBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF23; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); const QString& getLightNodeName() const; const ParentNodesData& getParentNodesData() const; @@ -391,7 +450,7 @@ class PDF3D_U3D_ViewNodeBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF24; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct BackdropOrOverlay { @@ -464,7 +523,7 @@ class PDF3D_U3D_CLODMeshDeclarationBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF31; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct BoneJoint { @@ -573,7 +632,7 @@ class PDF3D_U3D_CLODBaseMeshContinuationBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF3B; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct BaseCornerInfo { @@ -632,7 +691,7 @@ class PDF3D_U3D_CLODProgressiveMeshContinuationBlock : public PDF3D_U3D_Abstract public: static constexpr uint32_t ID = 0xFFFFFF3C; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct NewFacePositionInfo { @@ -669,7 +728,7 @@ class PDF3D_U3D_LineSetDeclarationBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF37; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); const QString& getName() const { return m_lineSetName; } uint32_t getLineCount() const; @@ -723,7 +782,7 @@ class PDF3D_U3D_LineSetContinuationBlock : public PDF3D_U3D_AbstractBlock public: static constexpr uint32_t ID = 0xFFFFFF3F; - static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D* object); + static PDF3D_U3D_AbstractBlockPtr parse(QByteArray data, QByteArray metaData, PDF3D_U3D_Parser* object); struct NewLineEndingInfo { @@ -778,52 +837,8 @@ class PDF4QTLIBSHARED_EXPORT PDF3D_U3D public: PDF3D_U3D(); - bool isCompressed() const { return m_isCompressed; } - QTextCodec* getTextCodec() const { return m_textCodec; } - - static PDF3D_U3D parse(QByteArray data); - - static void processBlock(PDF3D_U3D& object, - const PDF3D_U3D_Block_Data& blockData, - PDF3D_U3D_DecoderLists& decoderLists, - QStringList& errors, - PDF3D_U3D_DecoderLists::EPalette palette); - const PDF3D_U3D_CLODMeshDeclarationBlock* getCLODMeshDeclarationBlock(const QString& meshName) const; const PDF3D_U3D_LineSetDeclarationBlock* getLineSetDeclarationBlock(const QString& lineSetName) const; - - template - const T* getBlock(const QString& name) const; - - PDF3D_U3D_AbstractBlockPtr parseBlockWithDeclaration(PDF3D_U3D_DataReader& reader); - PDF3D_U3D_ContextManager* getContextManager() { return m_contextManager.lock().get(); } - void setContextManager(std::weak_ptr contextManager) { m_contextManager = std::move(contextManager); } - - static PDF3D_U3D_Block_Data readBlockData(PDF3D_U3D_DataReader& reader); - -private: - PDF3D_U3D_AbstractBlockPtr parseBlock(uint32_t blockType, const QByteArray& data, const QByteArray& metaData); - PDF3D_U3D_AbstractBlockPtr parseBlock(const PDF3D_U3D_Block_Data& data); - static uint32_t getBlockPadding(uint32_t blockSize); - static bool isContinuationBlock(uint32_t blockType); - - struct LoadBlockInfo - { - QString typeName; - bool success = false; - uint32_t blockType = 0; - uint32_t dataSize = 0; - uint32_t metaDataSize = 0; - PDF3D_U3D_AbstractBlockPtr block; - }; - - PDF3D_U3D_AbstractBlockPtr m_fileBlock; - std::vector m_blocks; - std::vector m_allBlocks; - QTextCodec* m_textCodec = nullptr; - bool m_isCompressed = true; - uint32_t m_priority = 0; - std::weak_ptr m_contextManager; }; // ------------------------------------------------------------------------------- @@ -880,49 +895,97 @@ public: static constexpr uint32_t S_MAXIMUM_SYMBOL_IN_HISTOGRAM = 0x0000FFFF; }; -struct PDF3D_U3D_DecorderList_ChainItem -{ - std::vector blocks; -}; - -class PDF3D_U3D_DecoderList +class PDF3D_U3D_Decoder +{ +public: + + void addBlock(const PDF3D_U3D_Block_Data& block) { m_blocks.push_back(block); } + +private: + std::vector m_blocks; +}; + +class PDF3D_U3D_DecoderChain { public: - PDF3D_U3D_DecoderList() = default; const QString& getName() const; void setName(const QString& newName); - const std::vector& getChains() const; - void setChains(const std::vector& newChains); - PDF3D_U3D_DecorderList_ChainItem* getChain(size_t index); - - void createChain(const PDF3D_U3D_Block_Data& data); + PDF3D_U3D_Decoder* getDecoder(uint32_t chainPosition); + void addDecoder(PDF3D_U3D_Decoder&& decoder) { m_decoders.emplace_back(std::move(decoder)); } private: QString m_name; - std::vector m_chains; + std::vector m_decoders; }; -class PDF3D_U3D_DecoderLists +class PDF3D_U3D_DecoderPalette { public: - enum EPalette - { - Node, - View, - Light, - LastPalette - }; - - PDF3D_U3D_DecoderList* getDecoderList(QString name); - - bool addContinuationBlock(QString name, uint32_t chainIndex, const PDF3D_U3D_Block_Data& data); - void addDecoderList(PDF3D_U3D_DecoderList&& list) { m_decoderLists.emplace_back(std::move(list)); } + PDF3D_U3D_DecoderChain* getDecoderChain(const QString& name); + PDF3D_U3D_DecoderChain* createDecoderChain(const QString& name); private: - std::vector m_decoderLists; + std::vector m_decoderChains; +}; + +class PDF3D_U3D_DecoderPalettes +{ +public: + using EPalette = PDF3D_U3D_Block_Info::EPalette; + + PDF3D_U3D_DecoderPalette* getDecoderPalette(EPalette palette); + +private: + std::array m_decoderLists; +}; + +class PDF4QTLIBSHARED_EXPORT PDF3D_U3D_Parser +{ +public: + PDF3D_U3D_Parser(); + + PDF3D_U3D parse(QByteArray data); + + void processBlock(const PDF3D_U3D_Block_Data& blockData, PDF3D_U3D_Block_Info::EPalette palette); + void processModifierBlock(const PDF3D_U3D_Block_Data& blockData); + void processGenericBlock(const PDF3D_U3D_Block_Data& blockData, PDF3D_U3D_Block_Info::EPalette palette); + + PDF3D_U3D_ContextManager* getContextManager() { return &m_contextManager; } + bool isCompressed() const { return m_isCompressed; } + QTextCodec* getTextCodec() const { return m_textCodec; } + + PDF3D_U3D_AbstractBlockPtr parseBlock(uint32_t blockType, const QByteArray& data, const QByteArray& metaData); + PDF3D_U3D_AbstractBlockPtr parseBlock(const PDF3D_U3D_Block_Data& data); + + static uint32_t getBlockPadding(uint32_t blockSize); + + static PDF3D_U3D_Block_Data readBlockData(PDF3D_U3D_DataReader& reader); + +private: + struct LoadBlockInfo + { + QString typeName; + bool success = false; + PDF3D_U3D_Block_Info::EBlockType blockType = PDF3D_U3D_Block_Info::EBlockType(); + uint32_t dataSize = 0; + uint32_t metaDataSize = 0; + PDF3D_U3D_AbstractBlockPtr block; + }; + + std::vector m_blocks; + std::vector m_allBlocks; + + QStringList m_errors; + PDF3D_U3D_DecoderPalettes m_decoderLists; + PDF3D_U3D_ContextManager m_contextManager; + PDF3D_U3D m_object; + PDF3D_U3D_AbstractBlockPtr m_fileBlock; + QTextCodec* m_textCodec = nullptr; + bool m_isCompressed = true; + uint32_t m_priority = 0; }; class PDF3D_U3D_DataReader diff --git a/Pdf4QtViewer/pdfmediaviewerdialog.cpp b/Pdf4QtViewer/pdfmediaviewerdialog.cpp index 19fa48f..0638c66 100644 --- a/Pdf4QtViewer/pdfmediaviewerdialog.cpp +++ b/Pdf4QtViewer/pdfmediaviewerdialog.cpp @@ -198,15 +198,17 @@ void PDFMediaViewerDialog::initFrom3DAnnotation(const pdf::PDFDocument* document { case pdf::PDF3DStream::Type::U3D: { - QString file = "K:\\Programming\\PDF\\PDF_For_Qt\\U3D_parser\\u3d-tools\\src\\test.u3d"; + // TODO: Smazat + /*QString file = "K:\\Programming\\PDF\\PDF_For_Qt\\U3D_parser\\u3d-tools\\src\\test.u3d"; QFile f(file); if (f.open(QFile::WriteOnly | QFile::Truncate)) { f.write(data); f.close(); - } + }*/ - pdf::u3d::PDF3D_U3D u3d = pdf::u3d::PDF3D_U3D::parse(data); + pdf::u3d::PDF3D_U3D_Parser parser; + pdf::u3d::PDF3D_U3D u3d = parser.parse(data); break; }