#include "Converter2OOXML.h" #include "../../../DesktopEditor/common/File.h" #include "../../../DesktopEditor/common/Directory.h" #include "../../../DesktopEditor/common/SystemUtils.h" #include "../../../DesktopEditor/raster/BgraFrame.h" #include "../../../OfficeUtils/src/OfficeUtils.h" #include "../../../DesktopEditor/graphics/pro/Graphics.h" #include "../Paragraph/ParaText.h" #include "../Paragraph/CtrlCharacter.h" #include "../Paragraph/CtrlSectionDef.h" #include "../Paragraph/CtrlAutoNumber.h" #include "../Paragraph/CtrlTable.h" #include "../Paragraph/CtrlShapeRect.h" #include "../Paragraph/CtrlShapeArc.h" #include "../Paragraph/CtrlShapeLine.h" #include "../Paragraph/CtrlEqEdit.h" #include "../Paragraph/CtrlNote.h" #include "../HWPElements/HWPRecordBinData.h" #include "../HWPElements/HWPRecordParaShape.h" #include "../HWPElements/HWPRecordCharShape.h" #include "Transform.h" #include #include #define DEFAULT_FONT_FAMILY std::wstring(L"Arial") #define DEFAULT_FONT_SIZE 18 #define DEFAULT_LANGUAGE std::wstring(L"en") #define PARA_SPACING_SCALE 0.85 #define SPACING_SCALE_MS_WORD 1.21 namespace HWP { enum class EShapeObjectType { Arc, Curve, Ellipse, Line, Ole, Picture, Polygon, Rectangle, Unknown }; EShapeObjectType GetShapeObjectType(const std::wstring& wsID) { if (L"cra$" == wsID) return EShapeObjectType::Arc; if (L"ruc$" == wsID) return EShapeObjectType::Curve; if (L"lle$" == wsID) return EShapeObjectType::Ellipse; if (L"nil$" == wsID || L"loc$" == wsID) return EShapeObjectType::Line; if (L"elo$" == wsID) return EShapeObjectType::Ole; if (L"cip$" == wsID) return EShapeObjectType::Picture; if (L"lop$" == wsID) return EShapeObjectType::Polygon; if (L"cer$" == wsID) return EShapeObjectType::Rectangle; return EShapeObjectType::Unknown; } CConverter2OOXML::CConverter2OOXML() : m_pHWPFile(nullptr), m_ushShapeCount(0), m_ushPageCount(1), m_ushTableCount(0), m_ushEquationCount(0) {} CConverter2OOXML::~CConverter2OOXML() {} void CConverter2OOXML::SetHWPFile(CHWPFile_Private* pHWPFile) { m_pHWPFile = pHWPFile; } void CConverter2OOXML::SetTempDirectory(const HWP_STRING& sTempDirectory) { m_sTempDirectory = sTempDirectory; m_oOleConverter.SetTempDir(m_sTempDirectory); } void CConverter2OOXML::CreateEmptyFiles() { NSDirectory::CreateDirectory(m_sTempDirectory + L"/_rels"); NSDirectory::CreateDirectory(m_sTempDirectory + L"/docProps"); NSDirectory::CreateDirectory(m_sTempDirectory + L"/word"); NSDirectory::CreateDirectory(m_sTempDirectory + L"/word/_rels"); NSDirectory::CreateDirectory(m_sTempDirectory + L"/word/media"); NSDirectory::CreateDirectory(m_sTempDirectory + L"/word/theme"); // theme1.xml std::wstring wsTheme = L""; NSFile::CFileBinary oThemeWriter; if (oThemeWriter.CreateFileW(m_sTempDirectory + L"/word/theme/theme1.xml")) { oThemeWriter.WriteStringUTF8(wsTheme); oThemeWriter.CloseFile(); } // app.xml std::wstring wsApplication = NSSystemUtils::GetEnvVariable(NSSystemUtils::gc_EnvApplicationName); if (wsApplication.empty()) wsApplication = NSSystemUtils::gc_EnvApplicationNameDefault; std::wstring wsApp = L""; wsApp += wsApplication; wsApp += L"0falsefalsefalsefalse"; NSFile::CFileBinary oAppWriter; if (oAppWriter.CreateFileW(m_sTempDirectory + L"/docProps/app.xml")) { oAppWriter.WriteStringUTF8(wsApp); oAppWriter.CloseFile(); } // .rels std::wstring wsRels = L""; NSFile::CFileBinary oRelsWriter; if (oRelsWriter.CreateFileW(m_sTempDirectory + L"/_rels/.rels")) { oRelsWriter.WriteStringUTF8(wsRels); oRelsWriter.CloseFile(); } // fontTable.xml std::wstring wsFontTable = L""; NSFile::CFileBinary oFontTableWriter; if (oFontTableWriter.CreateFileW(m_sTempDirectory + L"/word/fontTable.xml")) { oFontTableWriter.WriteStringUTF8(wsFontTable); oFontTableWriter.CloseFile(); } // settings.xml std::wstring wsSettings = L""; NSFile::CFileBinary oSettingsWriter; if (oSettingsWriter.CreateFileW(m_sTempDirectory + L"/word/settings.xml")) { oSettingsWriter.WriteStringUTF8(wsSettings); oSettingsWriter.CloseFile(); } // core.xml std::wstring wsCore = L""; wsCore += L""; NSFile::CFileBinary oCoreWriter; if (oCoreWriter.CreateFileW(m_sTempDirectory + L"/docProps/core.xml")) { oCoreWriter.WriteStringUTF8(wsCore); oCoreWriter.CloseFile(); } FillDefaultData(); } void CConverter2OOXML::FillDefaultData() { // Заполняем начало файлов AddRelationship(L"styles", L"styles.xml"); AddRelationship(L"settings", L"settings.xml"); AddRelationship(L"webSettings", L"webSettings.xml"); AddRelationship(L"fontTable", L"fontTable.xml"); AddRelationship(L"theme", L"theme/theme1.xml"); m_oNoteXmlRels.WriteString(L""); m_oDocXml .WriteString(L""); m_oWebSettings.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oStylesXml.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); m_oContentTypes.WriteString(L""); } void CConverter2OOXML::Close() { // Дописываем концы файлов m_oDocXml.WriteString(L""); NSFile::CFileBinary oDocumentWriter; if (oDocumentWriter.CreateFileW(m_sTempDirectory + L"/word/document.xml")) { oDocumentWriter.WriteStringUTF8(m_oDocXml.GetData()); oDocumentWriter.CloseFile(); } if (m_oFootnoteConverter.SaveToFile(m_sTempDirectory + FILE_SEPARATOR_STR + L"word" + FILE_SEPARATOR_STR)) { AddRelationship(L"footnotes", L"footnotes.xml"); AddRelationship(L"endnotes", L"endnotes.xml"); AddContentType(L"footnotes.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml"); AddContentType(L"endnotes.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml"); } // styles.xml m_oStylesXml.WriteString(L""); NSFile::CFileBinary oStylesWriter; if (oStylesWriter.CreateFileW(m_sTempDirectory + L"/word/styles.xml")) { oStylesWriter.WriteStringUTF8(m_oStylesXml.GetData()); oStylesWriter.CloseFile(); } // numbering.xml if (m_oNumberingConverter.SaveToFile(m_sTempDirectory + FILE_SEPARATOR_STR + L"word" + FILE_SEPARATOR_STR)) { AddRelationship(L"numbering", L"numbering.xml"); AddContentType(L"numbering.xml", L"application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml"); } // webSettings.xml m_oWebSettings.WriteString(L""); NSFile::CFileBinary oWebSettingsWriter; if (oWebSettingsWriter.CreateFileW(m_sTempDirectory + L"/word/webSettings.xml")) { oWebSettingsWriter.WriteStringUTF8(m_oWebSettings.GetData()); oWebSettingsWriter.CloseFile(); } // [Content_Types].xml m_oContentTypes.WriteString(L""); NSFile::CFileBinary oContentTypeWriter; if (oContentTypeWriter.CreateFileW(m_sTempDirectory + L"/[Content_Types].xml")) { oContentTypeWriter.WriteStringUTF8(m_oContentTypes.GetData()); oContentTypeWriter.CloseFile(); } NSFile::CFileBinary oRelsWriter; if (oRelsWriter.CreateFileW(m_sTempDirectory + L"/word/_rels/document.xml.rels")) { oRelsWriter.WriteStringUTF8(L""); for (const TRelationship& oRelationship : m_arRelationships) oRelsWriter.WriteStringUTF8(L""); oRelsWriter.WriteStringUTF8(L""); oRelsWriter.CloseFile(); } } void CConverter2OOXML::Convert() { TConversionState oState; for (const CHWPSection* pSection : m_pHWPFile->GetSections()) { const bool bIsLastSection = pSection == m_pHWPFile->GetSections().back(); for (const CHWPPargraph *pPara : pSection->GetParagraphs()) { WriteParagraph(pPara, m_oDocXml, oState); } if (!bIsLastSection) m_oDocXml.WriteString(L""); WriteSectionSettings(oState); if (!bIsLastSection) m_oDocXml.WriteString(L""); ++oState.m_ushSecdIndex; } } bool CConverter2OOXML::IsRasterFormat(const HWP_STRING& sFormat) { return L"png" == sFormat || L"jpg" == sFormat || L"jpeg" == sFormat; } void CConverter2OOXML::WriteParagraph(const CHWPPargraph* pParagraph, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { if (nullptr == pParagraph) return; if (0 < pParagraph->GetBreakType()) { if ((0x01 == (pParagraph->GetBreakType() & 0x01) || 0x02 == (pParagraph->GetBreakType() & 0x02)) && 0 < oState.m_ushSecdIndex) { if (oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); oState.m_bOpenedP = true; ++m_ushPageCount; } else if (0x08 == (pParagraph->GetBreakType() & 0x08)) { if (oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); oState.m_bOpenedP = true; } } VECTOR arNoteRef; for (const CCtrl* pCtrl : pParagraph->GetCtrls()) { if (nullptr != dynamic_cast(pCtrl)) { std::wstring wsText = ((const CParaText*)pCtrl)->GetText(); if (wsText.empty()) wsText = L" "; WriteText(wsText, pParagraph->GetShapeID(), ((const CParaText*)pCtrl)->GetCharShapeID(), oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { const CCtrlCharacter *pCtrlCharacter = (const CCtrlCharacter*)pCtrl; switch (pCtrlCharacter->GetType()) { case ECtrlCharType::PARAGRAPH_BREAK: { if (oState.m_bOpenedP) { oState.m_bOpenedP = false; oBuilder.WriteString(L""); } oState.m_bNeedLineBreak = false; break; } case ECtrlCharType::LINE_BREAK: { oState.m_bNeedLineBreak = true; break; } case ECtrlCharType::HARD_HYPHEN: case ECtrlCharType::HARD_SPACE: break; } } else if (nullptr != dynamic_cast(pCtrl)) { WritePicture((const CCtrlShapePic*)pCtrl, oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { WriteTable((const CCtrlTable*)pCtrl, pParagraph->GetShapeID(), oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl) || nullptr != dynamic_cast(pCtrl) || nullptr != dynamic_cast(pCtrl) || nullptr != dynamic_cast(pCtrl)) { WriteGeometryShape((const CCtrlGeneralShape*)pCtrl, oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { WriteEqEditShape((const CCtrlEqEdit*)pCtrl, oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { WriteOleShape((const CCtrlShapeOle*)pCtrl, oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { arNoteRef.push_back(m_oFootnoteConverter.CreateNote((const CCtrlNote*)pCtrl, *this)); } else if (nullptr != dynamic_cast(pCtrl)) oState.m_pSectionDef = (const CCtrlSectionDef*)pCtrl; else if (nullptr != dynamic_cast(pCtrl)) oState.m_pColumnDef = (const CCtrlColumnDef*)(pCtrl); else if (nullptr != dynamic_cast(pCtrl)) { unsigned short ushValue = 0; //TODO:: лучше перейти не на ручной подсчет, а на автоматический в word (но там есть свои проблемы) switch (((const CCtrlAutoNumber*)pCtrl)->GetNumType()) { case ENumType::PAGE: case ENumType::TOTAL_PAGE: ushValue = m_ushPageCount; break; case ENumType::FOOTNOTE: ushValue = m_oFootnoteConverter.GetFootnoteCount(); break; case ENumType::ENDNOTE: ushValue = m_oFootnoteConverter.GetEndnoteCount(); break; case ENumType::FIGURE: ushValue = m_ushShapeCount; break; case ENumType::TABLE: ushValue = m_ushTableCount; break; case ENumType::EQUATION: ushValue = m_ushEquationCount; break; case ENumType::null: break; } if (0 == ushValue) continue; WriteText(std::to_wstring(ushValue), pParagraph->GetShapeID(), ((const CParaText*)pCtrl)->GetCharShapeID(), oBuilder, oState); } else if (nullptr != dynamic_cast(pCtrl)) { WriteVideo((const CCtrlShapeVideo*)pCtrl, oBuilder, oState); } else continue; if (!arNoteRef.empty() && nullptr == dynamic_cast(pCtrl) && oState.m_bOpenedP) { for (const std::wstring& wsNoteRef : arNoteRef) oBuilder.WriteString(L"" + wsNoteRef + L""); arNoteRef.clear(); } } if (oState.m_bOpenedP) { if (!arNoteRef.empty()) for (const std::wstring& wsNoteRef : arNoteRef) oBuilder.WriteString(L"" + wsNoteRef + L""); oBuilder.WriteString(L""); oState.m_bOpenedP = false; } } void CConverter2OOXML::WriteParagraphProperties(short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { oBuilder.WriteString(L""); WriteParaShapeProperties(shParaShapeID, oBuilder, oState); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteParaShapeProperties(short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, const TConversionState& oState) { const CHWPDocInfo* pDocInfo = nullptr; if (nullptr != m_pHWPFile) pDocInfo = m_pHWPFile->GetDocInfo(); if (nullptr == m_pHWPFile) return; const CHWPRecordParaShape* pParaShape = dynamic_cast(pDocInfo->GetParaShape(shParaShapeID)); if (nullptr == pParaShape) return; oBuilder.WriteString(L"KeepWithNext()) ? L"true" : L"false") + L"\"/>"); switch(pParaShape->GetHorizantalAlign()) { case EHorizontalAlign::JUSTIFY: oBuilder.WriteString(L""); break; case EHorizontalAlign::LEFT: oBuilder.WriteString(L""); break; case EHorizontalAlign::RIGHT: oBuilder.WriteString(L""); break; case EHorizontalAlign::CENTER: oBuilder.WriteString(L""); break; case EHorizontalAlign::DISTRIBUTE: case EHorizontalAlign::DISTRIBUTE_SPACE: oBuilder.WriteString(L""); break; } switch(pParaShape->GetVerticalAlign()) { case EVerticalAlign::BOTTOM: oBuilder.WriteString(L""); break; case EVerticalAlign::TOP: oBuilder.WriteString(L""); break; case EVerticalAlign::CENTER: oBuilder.WriteString(L""); break; case EVerticalAlign::BASELINE: break; } int nLineSpacing = 0; HWP_STRING sType = L"auto"; switch(pParaShape->GetLineSpacingType()) { case 0x0: { sType = L"auto"; nLineSpacing = static_cast(240. * (double)pParaShape->GetLineSpacing() / 100.); break; } case 0x01: { sType = L"exact"; nLineSpacing = static_cast((double)pParaShape->GetLineSpacing() / 2. * 20)/*0.352778*/; //(1pt=0.352778mm) //TODO:: проверить, как найдется пример break; } case 0x02: case 0x03: default: { sType = L"atLeast"; nLineSpacing = static_cast((double)pParaShape->GetLineSpacing()); //TODO:: проверить, как найдется пример break; } } oBuilder.WriteString(L"((double)pParaShape->GetMarginPrev() / 10.)) + L"\" w:after=\"" + std::to_wstring(static_cast((double)pParaShape->GetMarginNext() / 10.)) + L"\"/>"); switch (pParaShape->GetHeadingType()) { case EHeadingType::NUMBER: case EHeadingType::BULLET: { const int nNumId = m_oNumberingConverter.CreateNumbering(dynamic_cast(pDocInfo->GetNumbering(pParaShape->GetHeadingIdRef())), pParaShape->GetHeadingType()); if (0 == nNumId) break; oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); break; } case EHeadingType::OUTLINE: case EHeadingType::NONE: break; } } void CConverter2OOXML::WriteTable(const CCtrlTable* pTable, short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { if (nullptr == pTable || pTable->Empty()) return; ++m_ushTableCount; oBuilder.WriteString(L""); WriteTableProperties(pTable, shParaShapeID, oBuilder, oState); std::vector>> m_arrCells(pTable->GetRows()); for (unsigned int unRowIndex = 0; unRowIndex < pTable->GetRows(); ++unRowIndex) { m_arrCells[unRowIndex].resize(pTable->GetCols()); for (unsigned int unColIndex = 0; unColIndex < pTable->GetCols(); ++unColIndex) m_arrCells[unRowIndex][unColIndex] = std::make_pair(ECellCreator::NOT_CREATED, nullptr); } for (unsigned int unCellIndex = 0; unCellIndex < pTable->GetCountCells(); ++unCellIndex) { const CTblCell* pCell = pTable->GetCell(unCellIndex); if (nullptr == pCell || pCell->GetRowAddr() >= pTable->GetRows() || pCell->GetColAddr() >= pTable->GetCols()) continue; m_arrCells[pCell->GetRowAddr()][pCell->GetColAddr()] = std::make_pair(ECellCreator::FILE, pCell); } for (unsigned int unRowIndex = 0; unRowIndex < pTable->GetRows(); ++unRowIndex) { for (unsigned int unColIndex = 0; unColIndex < pTable->GetCols(); ++unColIndex) { std::pair oValue = m_arrCells[unRowIndex][unColIndex]; if (ECellCreator::NOT_CREATED == oValue.first) continue; if (ECellCreator::FILE == oValue.first) { if (1 != oValue.second->GetRowSpan()) { for (unsigned int unIndex = 1; unIndex < oValue.second->GetRowSpan() && unRowIndex + unIndex < pTable->GetRows(); ++unIndex) m_arrCells[unRowIndex + unIndex][unColIndex] = std::make_pair(ECellCreator::EMPTY, oValue.second); } } unColIndex += oValue.second->GetColSpan() - 1; } } //TODO:: в случаях, когда есть пустые столбцы необходимо добавить возможность удаления данных столбцов // Например для матрицы 3x2, у которой значения есть только в 2x2, необходимо удалить последний столбец for (unsigned int unRowIndex = 0; unRowIndex < pTable->GetRows(); ++unRowIndex) { oBuilder.WriteString(L""); int nHeight = 0; for (unsigned int unColIndex = 0; unColIndex < pTable->GetCols(); ++unColIndex) { std::pair oValue = m_arrCells[unRowIndex][unColIndex]; if (ECellCreator::FILE == oValue.first && 1 == oValue.second->GetRowSpan()) nHeight = (std::max)(nHeight, oValue.second->GetHeight()); } oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); for (unsigned int unColIndex = 0; unColIndex < pTable->GetCols(); ++unColIndex) { std::pair oValue = m_arrCells[unRowIndex][unColIndex]; WriteCell(oValue.second, oBuilder, oState, oValue.first); } oBuilder.WriteString(L""); } oBuilder.WriteString(L""); } void CConverter2OOXML::WriteTableProperties(const CCtrlTable* pTable, short shParaShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { if (nullptr == pTable) return; oBuilder.WriteString(L""); oBuilder.WriteString(L""); WriteParaShapeProperties(shParaShapeID, oBuilder, oState); const CHWPRecordBorderFill* pBorderFill = nullptr; if (nullptr != m_pHWPFile) pBorderFill = dynamic_cast(m_pHWPFile->GetDocInfo()->GetBorderFill(pTable->GetBorderFillID())); if (nullptr == pBorderFill) { oBuilder.WriteString(L""); return; } oBuilder.WriteString(L""); } void CConverter2OOXML::WriteCell(const CTblCell* pCell, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState, ECellCreator eCellCreator) { if (nullptr == pCell) return; oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetWidth())) + L"\" w:type=\"dxa\"/>"); if (1 != pCell->GetColSpan()) oBuilder.WriteString(L"GetColSpan()) + L"\"/>"); if (1 != pCell->GetRowSpan()) oBuilder.WriteString(L""); WriteCellProperties(pCell->GetBorderFillID(), oBuilder); switch(pCell->GetVertAlign()) { case EVertAlign::TOP: oBuilder.WriteString(L""); break; case EVertAlign::CENTER: oBuilder.WriteString(L""); break; case EVertAlign::BOTTOM: oBuilder.WriteString(L""); break; case EVertAlign::INSIDE: case EVertAlign::OUTSIDE: break; } oBuilder.WriteString(L""); if (ECellCreator::FILE == eCellCreator && !pCell->GetParagraphs().empty()) { for (const CHWPPargraph* pParagraph : pCell->GetParagraphs()) { TConversionState oCellState; WriteParagraph(pParagraph, oBuilder, oCellState); } } else oBuilder.WriteString(L""); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteCellProperties(short shBorderFillID, NSStringUtils::CStringBuilder& oBuilder) { const CHWPRecordBorderFill* pBorderFill = nullptr; if (nullptr != m_pHWPFile) pBorderFill = dynamic_cast(m_pHWPFile->GetDocInfo()->GetBorderFill(shBorderFillID)); if (nullptr == pBorderFill) return; if (pBorderFill->GetFill()->ColorFill()) oBuilder.WriteString(L"GetFill()->GetFaceColor()) + L"\"/>"); oBuilder.WriteString(L""); WriteCellBorder(pBorderFill->GetTopBorder(), L"top", oBuilder); WriteCellBorder(pBorderFill->GetLeftBorder(), L"left", oBuilder); WriteCellBorder(pBorderFill->GetBottomBorder(), L"bottom", oBuilder); WriteCellBorder(pBorderFill->GetRightBorder(), L"right", oBuilder); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteCellBorder(const TBorder& oBorder, const HWP_STRING& sBorderName, NSStringUtils::CStringBuilder& oBuilder) { if (0x00 == oBorder.m_chWidth || sBorderName.empty()) return; HWP_STRING sType; //TODO:: проверить стиль линий switch(oBorder.m_eStyle) { case ELineStyle2::NONE: oBuilder.WriteString(L""); return; case ELineStyle2::SOLID: sType = L"single"; break; case ELineStyle2::DASH: sType = L"dashed"; break; case ELineStyle2::DOT: sType = L"dotted"; break; case ELineStyle2::DASH_DOT: sType = L"dotDash"; break; case ELineStyle2::DASH_DOT_DOT: sType = L"dotDotDash"; break; case ELineStyle2::LONG_DASH: sType = L"dashed"; break; case ELineStyle2::CIRCLE: sType = L"dashed"; break; case ELineStyle2::DOUBLE_SLIM: sType = L"thickThinMediumGap"; break; case ELineStyle2::SLIM_THICK: sType = L"thickThinMediumGap"; break; case ELineStyle2::THICK_SLIM: sType = L"thickThinMediumGap"; break; case ELineStyle2::SLIM_THICK_SLIM: sType = L"thickThinMediumGap"; break; break; } oBuilder.WriteString(L""); } void CConverter2OOXML::WriteGeometryShape(const CCtrlGeneralShape* pGeneralShape, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { if (nullptr == pGeneralShape) return; EShapeObjectType eShapeType = GetShapeObjectType(pGeneralShape->GetID()); if (EShapeObjectType::Unknown == eShapeType) return; const std::wstring wsWidth = std::to_wstring(Transform::HWPUINT2OOXML(pGeneralShape->GetWidth())); const std::wstring wsHeight = std::to_wstring(Transform::HWPUINT2OOXML(pGeneralShape->GetHeight())); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); OpenAnchorNode(pGeneralShape, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); switch (eShapeType) { case EShapeObjectType::Arc: { oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); break; } case EShapeObjectType::Ellipse: { oBuilder.WriteString(L""); break; } case EShapeObjectType::Line: { oBuilder.WriteString(L""); break; } case EShapeObjectType::Rectangle: { oBuilder.WriteString(L""); break; } case EShapeObjectType::Curve: case EShapeObjectType::Ole: case EShapeObjectType::Picture: case EShapeObjectType::Polygon: case EShapeObjectType::Unknown: break; } const CFill *pFill = pGeneralShape->GetFill(); if (nullptr == pFill || pFill->NoneFill()) oBuilder.WriteString(L""); else if (pFill->ColorFill()) oBuilder.WriteString(L"GetFaceColor()) + L"\"/>"); else if (pFill->ImageFill()) { const HWP_STRING sPictureId = SavePicture(pFill->GetBinItemID()); if (!sPictureId.empty()) oBuilder.WriteString(L""); else oBuilder.WriteString(L""); } WriteLineSettings(pGeneralShape, oBuilder); oBuilder.WriteString(L""); unsigned int nCountParagraphs = pGeneralShape->GetCountParagraphs(); if (0 < nCountParagraphs) { oBuilder.WriteString(L""); TConversionState oShapeState; for (unsigned int unParaIndex = 0; unParaIndex < nCountParagraphs; ++unParaIndex) WriteParagraph(pGeneralShape->GetParagraphs(unParaIndex), oBuilder, oShapeState); oBuilder.WriteString(L""); } oBuilder.WriteString(L""); oBuilder.WriteString(L""); CloseAnchorNode(oBuilder); oBuilder.WriteString(L""); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); } void CConverter2OOXML::WriteEqEditShape(const CCtrlEqEdit* pEqEditShape, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { //TODO:: добавить конвертацию eqn формулы в ooxml ++m_ushEquationCount; if (!oState.m_bOpenedP) { oBuilder.WriteString(L""); oState.m_bOpenedP = true; } oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteEncodeXmlString(pEqEditShape->GetEqn()); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteOleShape(const CCtrlShapeOle* pOleShape, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { //TODO:: добавить конвертацию hwp ole -> ooxml chart //TODO:: необходимо добавить поддержку формата "Hwp Document File Formats - Charts" (для случаев, когда нет ooxml представления) // Пока можем вытащить лишь ooxml представление данных CHWPStream oBuffer; HWP_STRING sFormat; if (!GetBinBytes(pOleShape->GetBinDataID(), oBuffer, sFormat)) return; m_oOleConverter.CreateChart(oBuffer); const unsigned int unChartIndex = m_oOleConverter.GetChartsCount(); if (0 == unChartIndex) return; const std::wstring wsWidth = std::to_wstring(Transform::HWPUINT2OOXML(pOleShape->GetWidth())); const std::wstring wsHeight = std::to_wstring(Transform::HWPUINT2OOXML(pOleShape->GetHeight())); const std::wstring wsRelID = AddRelationship(L"chart", L"charts/chart" + std::to_wstring(unChartIndex) + L".xml"); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); OpenAnchorNode(pOleShape, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); CloseAnchorNode(oBuilder); oBuilder.WriteString(L""); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); AddContentType(L"charts/chart" + std::to_wstring(unChartIndex), L"application/vnd.openxmlformats-officedocument.drawingml.chart+xml"); AddContentType(L"charts/style" + std::to_wstring(unChartIndex), L"application/vnd.ms-office.chartstyle+xml"); AddContentType(L"charts/colors" + std::to_wstring(unChartIndex), L"application/vnd.ms-office.chartcolorstyle+xml"); } void CConverter2OOXML::WriteSectionSettings(TConversionState& oState) { m_oDocXml.WriteString(L""); if (nullptr != oState.m_pSectionDef) { for (const CCtrlHeadFoot* pCtrlHeadFoot : oState.m_pSectionDef->GetHeaderFooters()) { const std::wstring wsID = m_oFootnoteConverter.CreateHeadOrFoot((const CCtrlHeadFoot*)pCtrlHeadFoot, *this); if (!wsID.empty() && wsID.length() > 6) { const std::wstring wsType = wsID.substr(0, 6); AddContentType(wsID, L"application/vnd.openxmlformats-officedocument.wordprocessingml." + wsType + L"+xml"); m_oDocXml.WriteString(L""); } } } if (nullptr != oState.m_pColumnDef && 1 < oState.m_pColumnDef->GetColCount()) { //TODO:: Добавить поддержку остальный свойств m_oDocXml.WriteString(L"GetColCount()) + L"\" w:space=\"454\" w:equalWidth=\"true\""); if (ELineStyle2::NONE != oState.m_pColumnDef->GetColLineStyle()) m_oDocXml.WriteString(L" w:sep=\"true\""); m_oDocXml.WriteString(L"/>"); } const CPage *pPage = (nullptr != oState.m_pSectionDef) ? oState.m_pSectionDef->GetPage() : nullptr; if (nullptr == pPage) { //DEFAULT_VALUE m_oDocXml.WriteString(L""); m_oDocXml.WriteString(L""); } else { m_oDocXml.WriteString(L"GetWidth())) + L"\" w:h=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetHeight())) + L"\"/>"); m_oDocXml.WriteString(L"GetMarginTop())) + L"\" w:right=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginRight())) + L"\" w:bottom=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginBottom())) + L"\" w:left=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginRight())) + L"\" w:header=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginHeader())) + L"\" w:footer=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginFooter())) + L"\" w:gutter=\"" + std::to_wstring(Transform::HWPUINT2Twips(pPage->GetMarginGutter())) + L"\"/>"); } m_oDocXml.WriteString(L""); m_oDocXml.WriteString(L""); m_oDocXml.WriteString(L""); } void CConverter2OOXML::WritePicture(const CCtrlShapePic* pCtrlPic, NSStringUtils::CStringBuilder& oBuilder, const TConversionState& oState) { if (nullptr == pCtrlPic) return; HWP_STRING sPictureID = SavePicture(pCtrlPic->GetBinDataID()); if (sPictureID.empty()) return; if (!oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); OpenAnchorNode(pCtrlPic, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetBinDataID() + L"\" name=\"Picture" + pCtrlPic->GetBinDataID() + L"\"/>"); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetCurWidth())) + L"\" cy=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlPic->GetCurHeight())) + L"\"/>"); oBuilder.WriteString(L""); WriteBorderSettings(pCtrlPic, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L"00"); CloseAnchorNode(oBuilder); oBuilder.WriteString(L""); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); } void CConverter2OOXML::WriteVideo(const CCtrlShapeVideo* pCtrlVideo, NSStringUtils::CStringBuilder& oBuilder, const TConversionState& oState) { if (nullptr == pCtrlVideo) return; HWP_STRING sPictureID = SavePicture(pCtrlVideo->GetThumnailBinID()); if (sPictureID.empty()) return; if (!oState.m_bOpenedP) oBuilder.WriteString(L""); oBuilder.WriteString(L""); OpenAnchorNode(pCtrlVideo, oBuilder); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetThumnailBinID() + L"\" name=\"Video " + pCtrlVideo->GetThumnailBinID() + L"\"/>"); oBuilder.WriteString(L""); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetCurWidth())) + L"\" cy=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlVideo->GetCurHeight())) + L"\"/>"); oBuilder.WriteString(L""); oBuilder.WriteString(L"00"); CloseAnchorNode(oBuilder); oBuilder.WriteString(L""); if (!oState.m_bOpenedP) oBuilder.WriteString(L""); } bool CConverter2OOXML::SaveSVGFile(const HWP_STRING& sSVG, const HWP_STRING& sIndex) { if (sSVG.empty()) return false; NSFonts::IApplicationFonts* pFonts = NSFonts::NSApplication::Create(); pFonts->Initialize(); MetaFile::IMetaFile* pSvgReader = MetaFile::Create(pFonts); if (!pSvgReader->LoadFromString(sSVG)) { RELEASEINTERFACE(pSvgReader); RELEASEINTERFACE(pFonts); return false; } NSGraphics::IGraphicsRenderer* pGrRenderer = NSGraphics::Create(); pGrRenderer->SetFontManager(pSvgReader->get_FontManager()); double dX, dY, dW, dH; pSvgReader->GetBounds(&dX, &dY, &dW, &dH); if (dW < 0) dW = -dW; if (dH < 0) dH = -dH; double dOneMaxSize = (double)1000.; if (dW > dH && dW > dOneMaxSize) { dH *= (dOneMaxSize / dW); dW = dOneMaxSize; } else if (dH > dW && dH > dOneMaxSize) { dW *= (dOneMaxSize / dH); dH = dOneMaxSize; } int nWidth = static_cast(dW + 0.5); int nHeight = static_cast(dH + 0.5); double dWidth = 25.4 * nWidth / 96; double dHeight = 25.4 * nHeight / 96; unsigned char* pBgraData = (unsigned char*)malloc(nWidth * nHeight * 4); if (!pBgraData) { double dKoef = 2000.0 / (nWidth > nHeight ? nWidth : nHeight); nWidth = (int)(dKoef * nWidth); nHeight = (int)(dKoef * nHeight); dWidth = 25.4 * nWidth / 96; dHeight = 25.4 * nHeight / 96; pBgraData = (unsigned char*)malloc(nWidth * nHeight * 4); } if (!pBgraData) return false; unsigned int alfa = 0xffffff; //дефолтный тон должен быть прозрачным, а не белым //memset(pBgraData, 0xff, nWidth * nHeight * 4); for (int i = 0; i < nWidth * nHeight; i++) { ((unsigned int*)pBgraData)[i] = alfa; } CBgraFrame oFrame; oFrame.put_Data(pBgraData); oFrame.put_Width(nWidth); oFrame.put_Height(nHeight); oFrame.put_Stride(-4 * nWidth); pGrRenderer->CreateFromBgraFrame(&oFrame); pGrRenderer->SetSwapRGB(false); pGrRenderer->put_Width(dWidth); pGrRenderer->put_Height(dHeight); pSvgReader->SetTempDirectory(m_sTempDirectory); pSvgReader->DrawOnRenderer(pGrRenderer, 0, 0, dWidth, dHeight); oFrame.SaveFile(m_sTempDirectory + L"/word/media/image" + sIndex + L".png", 4); oFrame.put_Data(NULL); RELEASEINTERFACE(pGrRenderer); if (pBgraData) free(pBgraData); RELEASEINTERFACE(pSvgReader); RELEASEINTERFACE(pFonts); return true; } HWP_STRING CConverter2OOXML::SavePicture(const HWP_STRING& sBinItemId) { //TODO:: добавить поддержку устновки размеров изображения из свойств шейпа CHWPStream oBuffer; HWP_STRING sFormat; if (!GetBinBytes(sBinItemId, oBuffer, sFormat)) return HWP_STRING(); oBuffer.MoveToStart(); if (IsRasterFormat(sFormat)) { NSFile::CFileBinary oFile; oFile.CreateFileW(m_sTempDirectory + L"/word/media/image" + sBinItemId + L'.' + sFormat); if (!oFile.WriteFile((unsigned char*)oBuffer.GetCurPtr(), oBuffer.GetSize())) { oFile.CloseFile(); return HWP_STRING(); } oFile.CloseFile(); } else if (L"svg" == sFormat) { std::string sSVG(oBuffer.GetCurPtr(), oBuffer.GetSize()); if (!SaveSVGFile(UTF8_TO_U(sSVG), sBinItemId)) return HWP_STRING(); sFormat = L"png"; } AddContentType(L"media/image" + sBinItemId + L'.' + sFormat, L"image/" + sFormat); return AddRelationship(L"image", L"media/image" + sBinItemId + L'.' + sFormat); } void CConverter2OOXML::WriteRunnerStyle(short shCharShapeID, NSStringUtils::CStringBuilder& oBuilder, const TConversionState& oState) { const CHWPDocInfo* pDocInfo = nullptr; if (nullptr != m_pHWPFile) { pDocInfo = m_pHWPFile->GetDocInfo(); const CHWPRecordCharShape* pCharShape = dynamic_cast(pDocInfo->GetCharShape(shCharShapeID)); if (nullptr == pCharShape) return; oBuilder.WriteString(L""); HWP_STRING sFontFamily = pCharShape->GetFontName(ELang::LATIN); HWP_STRING sFontFamilyAsian = pCharShape->GetFontName(ELang::HANGUL); if (sFontFamilyAsian.empty() && !sFontFamily.empty()) sFontFamilyAsian = sFontFamily; else if (!sFontFamilyAsian.empty() && sFontFamily.empty()) sFontFamily = sFontFamilyAsian; if (!sFontFamily.empty() && !sFontFamilyAsian.empty()) { oBuilder.WriteString(L""); } if (pCharShape->Bold()) oBuilder.WriteString(L""); if (pCharShape->Italic()) oBuilder.WriteString(L""); const int nHeight = static_cast(((double)(std::abs)(pCharShape->GetHeight()) * ((double)pCharShape->GetRelSize(ELang::LATIN) / 100.) / 100.) * 2.); oBuilder.WriteString(L""); oBuilder.WriteString(L"GetTextColor()) + L"\"/>"); if (pCharShape->Underline()) { EUnderline eUnderlineType = pCharShape->GetUnderlineType(); ELineStyle1 eUnderlineStyle = pCharShape->GetUnderlineStyle(); if (EUnderline::BOTTOM == eUnderlineType) { oBuilder.WriteString(L"GetUnderlineColor()) + L"\"/>"); } else if (EUnderline::CENTER == eUnderlineType) { if (eUnderlineStyle == ELineStyle1::DOUBLE_SLIM || eUnderlineStyle == ELineStyle1::DOUBLE_WAVE) oBuilder.WriteString(L""); else oBuilder.WriteString(L""); } } double dSpacing = ((double)pCharShape->GetHeight() / 100.) * ((double)pCharShape->GetSpacing(ELang::HANGUL) / 100) * 0.8 + 0.4; dSpacing *= 20; // pt to twips (20 = 1440 / 72) oBuilder.WriteString(L""); oBuilder.WriteString(L""); } } void CConverter2OOXML::OpenAnchorNode(const CCtrlCommon* pCtrlShape, NSStringUtils::CStringBuilder& oBuilder) { if (nullptr == pCtrlShape) return; oBuilder.WriteString(L"GetTextWrap() ? L"1" : L"0")) + L"\" relativeHeight=\"" + std::to_wstring(pCtrlShape->GetZOrder()) + L"\" distT=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetTopMargin() / 10)) + L"\" distB=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetBottomMargin() / 10)) + L"\" distL=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetLeftMargin() / 10)) + L"\" distR=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetRightMargin() / 10)) + L"\" simplePos=\"0\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"); WriteShapeProperty(pCtrlShape, oBuilder); } void CConverter2OOXML::CloseAnchorNode(NSStringUtils::CStringBuilder& oBuilder) { oBuilder.WriteString(L""); } HWP_STRING GetVRelativeFrom(EVRelTo eRelTo) { switch (eRelTo) { case EVRelTo::PARA: return L"paragraph"; case EVRelTo::PAPER: case EVRelTo::PAGE: case EVRelTo::null: return L"page"; } } HWP_STRING GetHRelativeFrom(EHRelTo eRelTo) { switch (eRelTo) { case EHRelTo::PAPER: case EHRelTo::PAGE: case EHRelTo::null: return L"page"; case EHRelTo::COLUMN: return L"column"; case EHRelTo::PARA: return L"character"; } } void CConverter2OOXML::WriteShapeProperty(const CCtrlCommon* pCtrlShape, NSStringUtils::CStringBuilder& oBuilder) { if (nullptr == pCtrlShape) return; oBuilder.WriteString(L""); oBuilder.WriteString(L"GetHorzRelTo()) + L"\">" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetHorzOffset())) + L""); oBuilder.WriteString(L"GetVertRelTo()) + L"\">" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetVertOffset())) + L""); oBuilder.WriteString(L"GetWidth())) + L"\" cy=\"" + std::to_wstring(Transform::HWPUINT2OOXML(pCtrlShape->GetHeight())) + L"\"/>"); oBuilder.WriteString(L""); switch (pCtrlShape->GetTextWrap()) { case ETextWrap::SQUARE: { oBuilder.WriteString(L"GetTextFlow()) { case 0x0: default: oBuilder.WriteString(L"bothSides"); break; case 0x1: oBuilder.WriteString(L"left"); break; case 0x2: oBuilder.WriteString(L"right"); break; case 0x3: oBuilder.WriteString(L"largest"); break; } oBuilder.WriteString(L"\"/>"); break; } case ETextWrap::TOP_AND_BOTTOM: { oBuilder.WriteString(L""); break; } case ETextWrap::BEHIND_TEXT: case ETextWrap::IN_FRONT_OF_TEXT: { oBuilder.WriteString(L""); break; } } oBuilder.WriteString(L"GetDesc()); oBuilder.WriteString(L"\"/>"); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteText(const std::wstring& wsText, short shParaShapeID, short shCharShapeID, NSStringUtils::CStringBuilder& oBuilder, TConversionState& oState) { if (!oState.m_bOpenedP) { oBuilder.WriteString(L""); oState.m_bOpenedP = true; WriteParagraphProperties(shParaShapeID, oBuilder, oState); } oBuilder.WriteString(L""); WriteRunnerStyle(shCharShapeID, oBuilder, oState); if (oState.m_bNeedLineBreak) { oBuilder.WriteString(L""); oState.m_bNeedLineBreak = false; } oBuilder.WriteString(L""); oBuilder.WriteEncodeXmlString(wsText); oBuilder.WriteString(L""); } void CConverter2OOXML::WriteLineSettings(const CCtrlGeneralShape* pCtrlGeneralShape, NSStringUtils::CStringBuilder& oBuilder) { if (nullptr == pCtrlGeneralShape) return; WriteLineSettings(pCtrlGeneralShape->GetLineStyle(), pCtrlGeneralShape->GetLineColor(), pCtrlGeneralShape->GetLineThick(), 1, oBuilder); } void CConverter2OOXML::WriteLineSettings(ELineStyle2 eLineStyle, int nColor, int nThick, HWP_BYTE nCompoundLineType, NSStringUtils::CStringBuilder& oBuilder) { if (ELineStyle2::NONE == eLineStyle || 0 >= nThick) { oBuilder.WriteString(L""); return; } oBuilder.WriteString(L""); oBuilder.WriteString(L""); switch (eLineStyle) { case ELineStyle2::DASH: { oBuilder.WriteString(L""); break; } case ELineStyle2::DOT: { oBuilder.WriteString(L""); break; } case ELineStyle2::DASH_DOT: { oBuilder.WriteString(L""); break; } case ELineStyle2::DASH_DOT_DOT: { oBuilder.WriteString(L""); break; } case ELineStyle2::LONG_DASH: { oBuilder.WriteString(L""); break; } case ELineStyle2::CIRCLE: { oBuilder.WriteString(L""); break; } default: break; } switch (nCompoundLineType) { case 0x00: { oBuilder.WriteString(L""); break; } case 0x01: { oBuilder.WriteString(L""); break; } } oBuilder.WriteString(L""); } void CConverter2OOXML::WriteBorderSettings(const CCtrlShapePic* pCtrlPic, NSStringUtils::CStringBuilder& oBuilder) { if (nullptr == pCtrlPic) return; WriteLineSettings(pCtrlPic->GetBorderLineStyle(), pCtrlPic->GetBorderColor(), pCtrlPic->GetBorderThick(), pCtrlPic->GetBorderCompoundLineType(), oBuilder); } bool CConverter2OOXML::GetBinBytes(const HWP_STRING& sID, CHWPStream& oBuffer, HWP_STRING& sFormat) { const CHWPDocInfo* pDocInfo = nullptr; if (nullptr != m_pHWPFile) { pDocInfo = m_pHWPFile->GetDocInfo(); const CHWPRecordBinData* pBinData = dynamic_cast(pDocInfo->GetBinData(sID)); if (nullptr == pBinData) return false; if (EType::LINK == pBinData->GetType()) { NSFile::CFileBinary oFile; unsigned char *pBuffer = nullptr; unsigned long ulSize = 0; oFile.ReadAllBytes(pBinData->GetPath(), &pBuffer, ulSize); oBuffer.SetStream((HWP_BYTE*)pBuffer, ulSize, false); sFormat = NSFile::GetFileExtention(pBinData->GetPath()); } else { std::wostringstream oStringStream; oStringStream << L"BIN" << std::setw(4) << std::setfill(L'0') << std::hex << pBinData->GetBinDataID() << L"." << pBinData->GetFormat(); sFormat = pBinData->GetFormat(); return m_pHWPFile->GetChildStream(oStringStream.str(), pBinData->GetCompressed(), oBuffer); } } return true; } HWP_STRING CConverter2OOXML::AddRelationship(const HWP_STRING& wsType, const HWP_STRING& wsTarget) { if (wsType.empty() || wsTarget.empty()) return HWP_STRING(); m_arRelationships.push_back({L"rId" + std::to_wstring(m_arRelationships.size() + 1), wsType, wsTarget}); return m_arRelationships.back().m_wsID; } void CConverter2OOXML::AddContentType(const HWP_STRING& wsName, const HWP_STRING& wsType) { if (wsName.empty() || wsType.empty()) return; m_oContentTypes.WriteString(L""); } bool CConverter2OOXML::ConvertToFile(const HWP_STRING& sFilePath) { if (nullptr == m_pHWPFile || sFilePath.empty()) return false; CreateEmptyFiles(); Convert(); Close(); COfficeUtils oZip; oZip.CompressFileOrDirectory(m_sTempDirectory, sFilePath); return true; } bool CConverter2OOXML::ConvertToDir(const HWP_STRING& sDirectoryPath) { if (nullptr == m_pHWPFile || sDirectoryPath.empty()) return false; SetTempDirectory(sDirectoryPath); CreateEmptyFiles(); Convert(); Close(); return true; } HWP_STRING CConverter2OOXML::GetTempDirectory() const { return m_sTempDirectory; } TConversionState::TConversionState() : m_bOpenedP(false), m_bOpenedR(false), m_bNeedLineBreak(false), m_ushSecdIndex(0), m_pSectionDef(nullptr), m_pColumnDef(nullptr) {} }