diff --git a/Common/OfficeFileFormatChecker.h b/Common/OfficeFileFormatChecker.h index 612d587302..ac4bd1ebf8 100644 --- a/Common/OfficeFileFormatChecker.h +++ b/Common/OfficeFileFormatChecker.h @@ -109,4 +109,5 @@ public: bool isMobiFormatFile(unsigned char* pBuffer, int dwBytes); bool isFB2FormatFile(unsigned char* pBuffer, int dwBytes); bool isXpsFile(const std::wstring& fileName); + bool isOFDFile(const std::wstring& fileName); }; diff --git a/Common/OfficeFileFormatChecker2.cpp b/Common/OfficeFileFormatChecker2.cpp index d1c39c5f6a..0ebc447d9f 100644 --- a/Common/OfficeFileFormatChecker2.cpp +++ b/Common/OfficeFileFormatChecker2.cpp @@ -797,6 +797,13 @@ bool COfficeFileFormatChecker::isOfficeFile(const std::wstring &_fileName) bufferDetect = NULL; return true; } + else if (isOFDFile(fileName)) + { + if (bufferDetect) + delete[] bufferDetect; + bufferDetect = NULL; + return true; + } else if (isMacFormatFile(fileName)) { if (bufferDetect) @@ -1712,6 +1719,8 @@ std::wstring COfficeFileFormatChecker::GetExtensionByType(int type) return L".djvu"; case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS: return L".xps"; + case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD: + return L".ofd"; case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_SVG: return L".svg"; case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLR: @@ -1891,6 +1900,8 @@ int COfficeFileFormatChecker::GetFormatByExtension(const std::wstring &sExt) return AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU; if (L".xps" == ext || L".oxps" == ext) return AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS; + if (L"ofd" == ext) + return AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD; if (L".jpg" == ext || L".jpeg" == ext || L".jpe" == ext || L".jfif" == ext) return AVS_OFFICESTUDIO_FILE_IMAGE_JPG; @@ -2029,3 +2040,26 @@ bool COfficeFileFormatChecker::isXpsFile(const std::wstring &fileName) } return false; } + +bool COfficeFileFormatChecker::isOFDFile(const std::wstring& fileName) +{ + COfficeUtils OfficeUtils(NULL); + + ULONG nBufferSize = 0; + BYTE *pBuffer = NULL; + + HRESULT hresult = OfficeUtils.LoadFileFromArchive(fileName, L"OFD.xml", &pBuffer, nBufferSize); + if (hresult == S_OK && pBuffer != NULL) + { + if (19 <= nBufferSize && NULL != strstr((char *)pBuffer, "ofd:OFD")) + nFileType = AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD; + + delete[] pBuffer; + pBuffer = NULL; + + if (nFileType != AVS_OFFICESTUDIO_FILE_UNKNOWN) + return true; + } + + return false; +} diff --git a/Common/OfficeFileFormats.h b/Common/OfficeFileFormats.h index e56af78f0e..5d3916cee6 100644 --- a/Common/OfficeFileFormats.h +++ b/Common/OfficeFileFormats.h @@ -103,6 +103,7 @@ #define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLRMenu AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0007 #define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_HTMLRCanvas AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0008 #define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_PDFA AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x0009 +#define AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD AVS_OFFICESTUDIO_FILE_CROSSPLATFORM + 0x000a #define AVS_OFFICESTUDIO_FILE_IMAGE 0x0400 #define AVS_OFFICESTUDIO_FILE_IMAGE_JPG AVS_OFFICESTUDIO_FILE_IMAGE + 0x0001 diff --git a/DesktopEditor/graphics/pro/officedrawingfile.h b/DesktopEditor/graphics/pro/officedrawingfile.h index 7681650e93..13f8c16601 100644 --- a/DesktopEditor/graphics/pro/officedrawingfile.h +++ b/DesktopEditor/graphics/pro/officedrawingfile.h @@ -40,6 +40,7 @@ enum OfficeDrawingFileType odftPDF = 0, odftXPS = 1, odftDJVU = 2, + odftOFD = 3, odftUndefined = 255 }; diff --git a/OFDFile/OFDFile.cpp b/OFDFile/OFDFile.cpp new file mode 100644 index 0000000000..be4ee8ca9b --- /dev/null +++ b/OFDFile/OFDFile.cpp @@ -0,0 +1,147 @@ +#include "OFDFile.h" +#include "src/OFDFile_Private.h" + +#ifndef DISABLE_PDF_CONVERTATION +#include "../PdfFile/PdfFile.h" +#endif + +COFDFile::COFDFile(NSFonts::IApplicationFonts* pFonts) + : m_pInternal(new COFDFile_Private(pFonts)) +{} + +COFDFile::~COFDFile() +{ + COFDFile::Close(); + + if (nullptr != m_pInternal) + delete m_pInternal; +} + +bool COFDFile::LoadFromFile(const std::wstring& file, const std::wstring& options, const std::wstring& owner_password, const std::wstring& user_password) +{ + if (nullptr == m_pInternal) + return false; + + Close(); + + return m_pInternal->LoadFromFile(file); +} + +bool COFDFile::LoadFromMemory(unsigned char* data, unsigned long length, const std::wstring& options, const std::wstring& owner_password, const std::wstring& user_password) +{ + if (nullptr == m_pInternal) + return false; + + Close(); + + return m_pInternal->LoadFromMemory(data, length); +} + +void COFDFile::Close() +{ + if (nullptr != m_pInternal) + m_pInternal->Close(); +} + +NSFonts::IApplicationFonts* COFDFile::GetFonts() +{ + return (nullptr != m_pInternal) ? m_pInternal->GetFonts() : nullptr; +} + +OfficeDrawingFileType COFDFile::GetType() +{ + return odftOFD; +} + +std::wstring COFDFile::GetTempDirectory() +{ + if (nullptr != m_pInternal) + return m_pInternal->GetTempDir(); + + return std::wstring(); +} + +void COFDFile::SetTempDirectory(const std::wstring& directory) +{ + if (nullptr != m_pInternal) + m_pInternal->SetTempDir(directory); +} + +int COFDFile::GetPagesCount() +{ + if (nullptr != m_pInternal) + return m_pInternal->GetPageCount(); + + return 0; +} + +void COFDFile::GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY) +{ + if (nullptr == m_pInternal) + return; + + m_pInternal->GetPageSize(nPageIndex, *pdWidth, *pdHeight); + + *pdDpiX = 25.4; + *pdDpiY = 25.4; +} + +void COFDFile::DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak, COfficeDrawingPageParams* pParams) +{ + if (nullptr == pRenderer || nullptr == m_pInternal) + return; + + m_pInternal->DrawPage(pRenderer, nPageIndex); +} + +#ifndef DISABLE_PDF_CONVERTATION +void COFDFile::ConvertToPdf(const std::wstring& wsDstPath) +{ + CPdfFile oPdf(GetFonts()); + oPdf.CreatePdf(); + bool bBreak = false; + + int nPagesCount = GetPagesCount(); + for (int nPageIndex = 0; nPageIndex < nPagesCount; nPageIndex++) + { + oPdf.NewPage(); + oPdf.BeginCommand(c_nPageType); + + double dPageDpiX = 96., dPageDpiY = 96.; + double dWidth = 0., dHeight = 0.; + + GetPageInfo(nPageIndex, &dWidth, &dHeight, &dPageDpiX, &dPageDpiY); + + dWidth *= 25.4 / dPageDpiX; + dHeight *= 25.4 / dPageDpiY; + + oPdf.put_Width(dWidth); + oPdf.put_Height(dHeight); + + DrawPageOnRenderer(&oPdf, nPageIndex, &bBreak); + + oPdf.EndCommand(c_nPageType); + +#ifdef _DEBUG + printf("page %d / %d\n", nPageIndex + 1, nPagesCount); +#endif + } + + oPdf.SaveToFile(wsDstPath); +} + +std::wstring COFDFile::GetInfo() +{ + return std::wstring(); +} + +unsigned char* COFDFile::GetStructure() +{ + return nullptr; +} + +unsigned char* COFDFile::GetLinks(int nPageIndex) +{ + return nullptr; +} +#endif diff --git a/OFDFile/OFDFile.h b/OFDFile/OFDFile.h new file mode 100644 index 0000000000..d94373c09d --- /dev/null +++ b/OFDFile/OFDFile.h @@ -0,0 +1,56 @@ +#ifndef OFDFILE_H +#define OFDFILE_H + +#ifndef OFD_USE_DYNAMIC_LIBRARY +#define OFD_DECL_EXPORT +#else +#include "../DesktopEditor/common/base_export.h" +#define OFD_DECL_EXPORT Q_DECL_EXPORT +#endif + +#include "../DesktopEditor/graphics/pro/officedrawingfile.h" +#include "../DesktopEditor/graphics/pro/Fonts.h" + +class COFDFile_Private; +class OFD_DECL_EXPORT COFDFile : public IOfficeDrawingFile +{ + COFDFile_Private* m_pInternal; +public: + COFDFile(NSFonts::IApplicationFonts* pFonts); + virtual ~COFDFile(); + + // Open + virtual bool LoadFromFile(const std::wstring& file, const std::wstring& options = L"", + const std::wstring& owner_password = L"", const std::wstring& user_password = L"") override; + virtual bool LoadFromMemory(unsigned char* data, unsigned long length, const std::wstring& options = L"", + const std::wstring& owner_password = L"", const std::wstring& user_password = L"") override; + + // Close + void Close() override; + + // Get IApplicationFonts for wrappers + virtual NSFonts::IApplicationFonts* GetFonts() override; + + // Type + virtual OfficeDrawingFileType GetType() override; + + // Temp directory + virtual std::wstring GetTempDirectory() override; + virtual void SetTempDirectory(const std::wstring& directory) override; + + // Pages info/draw + virtual int GetPagesCount() override; + virtual void GetPageInfo(int nPageIndex, double* pdWidth, double* pdHeight, double* pdDpiX, double* pdDpiY) override; + virtual void DrawPageOnRenderer(IRenderer* pRenderer, int nPageIndex, bool* pBreak, COfficeDrawingPageParams* pParams = NULL) override; + + #ifndef DISABLE_PDF_CONVERTATION + void ConvertToPdf(const std::wstring& wsDstPath); + #endif + + // Common methods for viewer + virtual std::wstring GetInfo() override; + virtual unsigned char* GetStructure() override; + virtual unsigned char* GetLinks(int nPageIndex) override; +}; + +#endif // OFDFILE_H diff --git a/OFDFile/OFDFile.pro b/OFDFile/OFDFile.pro new file mode 100644 index 0000000000..3bbb507895 --- /dev/null +++ b/OFDFile/OFDFile.pro @@ -0,0 +1,86 @@ +QT -= core gui + +VERSION = 1.0.0.1 +TARGET = OFDFile +TEMPLATE = lib + +CONFIG += shared +CONFIG += plugin + +CORE_ROOT_DIR = $$PWD/.. +PWD_ROOT_DIR = $$PWD + +include($$CORE_ROOT_DIR/Common/base.pri) +include($$CORE_ROOT_DIR/Common/3dParty/boost/boost.pri) + +DEFINES += OFD_USE_DYNAMIC_LIBRARY + +ADD_DEPENDENCY(graphics, kernel, UnicodeConverter, PdfFile) + +core_windows { +LIBS += -lgdi32 \ + -ladvapi32 \ + -luser32 \ + -lshell32 +} + +INCLUDEPATH += \ + $$CORE_ROOT_DIR/DesktopEditor/freetype-2.10.4/include \ + $$CORE_ROOT_DIR/DesktopEditor/freetype-2.10.4/include/freetype + +HEADERS += \ + OFDFile.h \ + src/Content/ImageObject.h \ + src/Content/PageBlock.h \ + src/Content/PathObject.h \ + src/IOFDElement.h \ + src/OFDFile_Private.h \ + src/Base.h \ + src/Content/Content.h \ + src/Content/GraphicUnit.h \ + src/Content/IPageBlock.h \ + src/Content/Layer.h \ + src/Content/TextObject.h \ + src/Document.h \ + src/Page.h \ + src/Res.h \ + src/Types/Color.h \ + src/Types/ColorSpace.h \ + src/Types/CommonData.h \ + src/Types/CompositeGraphicUnit.h \ + src/Types/DrawParam.h \ + src/Types/Font.h \ + src/Types/MultiMedia.h \ + src/Types/PageArea.h \ + src/Types/Signature.h \ + src/Types/TemplatePage.h \ + src/Utils/Types.h \ + src/Utils/Utils.h \ + src/Utils/XmlReader.h + +SOURCES += \ + OFDFile.cpp \ + src/Content/ImageObject.cpp \ + src/Content/PageBlock.cpp \ + src/Content/PathObject.cpp \ + src/OFDFile_Private.cpp \ + src/Base.cpp \ + src/Content/Content.cpp \ + src/Content/GraphicUnit.cpp \ + src/Content/Layer.cpp \ + src/Content/TextObject.cpp \ + src/Document.cpp \ + src/Page.cpp \ + src/Res.cpp \ + src/Types/Color.cpp \ + src/Types/ColorSpace.cpp \ + src/Types/CommonData.cpp \ + src/Types/CompositeGraphicUnit.cpp \ + src/Types/DrawParam.cpp \ + src/Types/Font.cpp \ + src/Types/MultiMedia.cpp \ + src/Types/PageArea.cpp \ + src/Types/Signature.cpp \ + src/Types/TemplatePage.cpp \ + src/Utils/Types.cpp \ + src/Utils/XmlReader.cpp diff --git a/OFDFile/src/Base.cpp b/OFDFile/src/Base.cpp new file mode 100644 index 0000000000..59404d12d4 --- /dev/null +++ b/OFDFile/src/Base.cpp @@ -0,0 +1,213 @@ +#include "Base.h" +#include "Utils/Utils.h" + +namespace OFD +{ +#define IF_CHECK_NODE(node_name, varible_name)\ +if (node_name == sNodeName)\ + varible_name = oLiteReader.GetText2() + +#define ELSE_IF_CHECK_NODE(node_name, varible_name)\ +else if (node_name == sNodeName)\ + varible_name = oLiteReader.GetText2() + +EDocUsege GetDocUsage(const std::wstring& wsValue) +{ + if (L"EBook" == wsValue) + return EDocUsege::EBook; + else if (L"ENewsPaper" == wsValue) + return EDocUsege::ENewsPaper; + else if (L"EMagnize" == wsValue) + return EDocUsege::EMagzine; + else + return EDocUsege::Normal; +} + +CDocInfo::CDocInfo() + : m_eDocUsage(EDocUsege::Normal) +{} + +bool CDocInfo::Read(CXmlReader& oLiteReader) +{ + if (L"ofd:DocInfo" != oLiteReader.GetName()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + + std::string sNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + IF_CHECK_NODE("ofd:DocID", m_wsDocId); + ELSE_IF_CHECK_NODE("ofd:Title", m_wsTitle); + ELSE_IF_CHECK_NODE("ofd:Author", m_wsAuthor); + ELSE_IF_CHECK_NODE("ofd:Subject", m_wsSubject); + ELSE_IF_CHECK_NODE("ofd:Abstruct", m_wsAbstact); + ELSE_IF_CHECK_NODE("ofd:CreationDate", m_wsCreationDate); + ELSE_IF_CHECK_NODE("ofd:ModDate", m_wsModDate); + ELSE_IF_CHECK_NODE("ofd:Cover", m_wsCover); + ELSE_IF_CHECK_NODE("ofd:Creator", m_wsCreator); + ELSE_IF_CHECK_NODE("ofd:CreatorVersion", m_wsCreatorVersion); + else if ("ofd:DocUsage" == sNodeName) + m_eDocUsage = GetDocUsage(oLiteReader.GetText2()); + } + + return true; +} + +void CDocBody::ReadSignatures(const std::wstring& wsFilePath, IFolder* pFolder) +{ + if (wsFilePath.empty() || !CanUseThisPath(wsFilePath, pFolder->getFullFilePath(L""))) + return; + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(CombinePaths(pFolder->getFullFilePath(L""), wsFilePath)) || !oLiteReader.ReadNextNode() || L"ofd:Signatures" != oLiteReader.GetName()) + return; + + const int nDepth = oLiteReader.GetDepth(); + std::string sNodeName; + unsigned int unMaxSignId = 0; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + if ("ofd:MaxSignId" == sNodeName) + unMaxSignId = oLiteReader.GetUInteger(); + else if ("ofd:Signature" == sNodeName) + { + if (0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + continue; + + do + { + if ("BaseLoc" == oLiteReader.GetNameA()) + AddToContainer(CSignature::Read(oLiteReader.GetText(), pFolder), m_arSignatures); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); + } + } +} + +CDocBody::CDocBody() +{} + +CDocBody::~CDocBody() +{ + ClearContainer(m_arSignatures); +} + +CDocBody* CDocBody::Read(CXmlReader& oLiteReader, IFolder* pFolder) +{ + if (L"ofd:DocBody" != oLiteReader.GetName()) + return nullptr; + + const int nDepth = oLiteReader.GetDepth(); + std::string sNodeName; + + CDocBody *pDocBody = new CDocBody(); + + if (nullptr == pDocBody) + return nullptr; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + if ("ofd:DocInfo" == sNodeName) + { + if (!pDocBody->m_oDocInfo.Read(oLiteReader)) + { + delete pDocBody; + return nullptr; + } + } + else if ("ofd:DocRoot" == sNodeName) + pDocBody->m_oDocument.Read(oLiteReader.GetText2(), pFolder); + else if ("ofd:Signatures" == sNodeName) + pDocBody->ReadSignatures(oLiteReader.GetText2(), pFolder); + } + + return pDocBody; +} + +bool CDocBody::DrawPage(IRenderer* pRenderer, int nPageIndex) const +{ + const bool bResult = m_oDocument.DrawPage(pRenderer, nPageIndex); + + for (const CSignature* pSignature : m_arSignatures) + if (pSignature->Draw(pRenderer, nPageIndex, nullptr)) + break; + + return bResult; +} + +unsigned int CDocBody::GetPageCount() const +{ + return m_oDocument.GetPageCount(); +} + +bool CDocBody::GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const +{ + return m_oDocument.GetPageSize(nPageIndex, dWidth, dHeight); +} + +CBase::CBase() +{} + +CBase::~CBase() +{ + for (CDocBody* pDocBody : m_arDocBodies) + RELEASEOBJECT(pDocBody); +} + +bool CBase::Read(IFolder* pFolder) +{ + if (nullptr == pFolder || !pFolder->existsXml(L"OFD.xml")) + return false; + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(pFolder->getFullFilePath(L"OFD.xml")) || !oLiteReader.ReadNextNode() || L"ofd:OFD" != oLiteReader.GetName()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + + CDocBody* pDocBody = nullptr; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + pDocBody = CDocBody::Read(oLiteReader, pFolder); + if (nullptr != pDocBody) + m_arDocBodies.push_back(pDocBody); + } + + return !m_arDocBodies.empty(); +} + +void CBase::DrawPage(IRenderer* pRenderer, int nPageIndex) const +{ + for (const CDocBody* pDocBody : m_arDocBodies) + if (pDocBody->DrawPage(pRenderer, nPageIndex)) + return; +} + +unsigned int CBase::GetPageCount() const +{ + unsigned int unCount = 0; + + for (const CDocBody* pDocBody : m_arDocBodies) + unCount += pDocBody->GetPageCount(); + + return unCount; +} + +void CBase::GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const +{ + for (const CDocBody* pDocBody : m_arDocBodies) + if (pDocBody->GetPageSize(nPageIndex, dWidth, dHeight)) + return; +} +} diff --git a/OFDFile/src/Base.h b/OFDFile/src/Base.h new file mode 100644 index 0000000000..a10c281b3b --- /dev/null +++ b/OFDFile/src/Base.h @@ -0,0 +1,79 @@ +#ifndef BASE_H +#define BASE_H + +#include "../../DesktopEditor/graphics/IRenderer.h" +#include "../../OfficeUtils/src/ZipFolder.h" + +#include "Document.h" +#include "Types/Signature.h" + +namespace OFD +{ +enum class EDocUsege +{ + Normal, + EBook, + ENewsPaper, + EMagzine +}; + +class CDocInfo +{ + std::wstring m_wsDocId; + std::wstring m_wsTitle; + std::wstring m_wsAuthor; + std::wstring m_wsSubject; + std::wstring m_wsAbstact; + + std::wstring m_wsCreationDate; + std::wstring m_wsModDate; + + EDocUsege m_eDocUsage; + std::wstring m_wsCover; + std::vector m_arKeywords; + + std::wstring m_wsCreator; + std::wstring m_wsCreatorVersion; + + std::vector m_arCustomData; +public: + CDocInfo(); + bool Read(CXmlReader& oLiteReader); +}; + +class CDocBody +{ + CDocInfo m_oDocInfo; + CDocument m_oDocument; + // std::wstring m_wsVersions; + std::vector m_arSignatures; + + void ReadSignatures(const std::wstring& wsFilePath, IFolder* pFolder); +public: + CDocBody(); + ~CDocBody(); + + static CDocBody* Read(CXmlReader& oLiteReader, IFolder* pFolder); + + bool DrawPage(IRenderer* pRenderer, int nPageIndex) const; + + unsigned int GetPageCount() const; + bool GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const; +}; + +class CBase +{ + std::vector m_arDocBodies; +public: + CBase(); + ~CBase(); + + bool Read(IFolder* pFolder); + void DrawPage(IRenderer* pRenderer, int nPageIndex) const; + + unsigned int GetPageCount() const; + void GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const; +}; +} + +#endif // BASE_H diff --git a/OFDFile/src/Content/Content.cpp b/OFDFile/src/Content/Content.cpp new file mode 100644 index 0000000000..6bfb81a733 --- /dev/null +++ b/OFDFile/src/Content/Content.cpp @@ -0,0 +1,41 @@ +#include "Content.h" + +namespace OFD +{ +CContent::CContent() +{} + +CContent::~CContent() +{ + for (CLayer* pLayer : m_arLayers) + delete pLayer; +} + +bool CContent::Read(CXmlReader& oLiteReader) +{ + if (L"ofd:Content" != oLiteReader.GetName()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:Layer" == wsNodeName) + m_arLayers.push_back(new CLayer(oLiteReader)); + } + + return false; +} + +void CContent::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer) + return; + + for (const CLayer* pLayer : m_arLayers) + pLayer->Draw(pRenderer, oCommonData); +} +} diff --git a/OFDFile/src/Content/Content.h b/OFDFile/src/Content/Content.h new file mode 100644 index 0000000000..2e90d8b175 --- /dev/null +++ b/OFDFile/src/Content/Content.h @@ -0,0 +1,21 @@ +#ifndef CONTENT_H +#define CONTENT_H + +#include "Layer.h" +#include "../Types/CommonData.h" + +namespace OFD +{ +class CContent +{ + std::vector m_arLayers; +public: + CContent(); + ~CContent(); + + bool Read(CXmlReader& oLiteReader); + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const; +}; +} + +#endif // CONTENT_H diff --git a/OFDFile/src/Content/GraphicUnit.cpp b/OFDFile/src/Content/GraphicUnit.cpp new file mode 100644 index 0000000000..8a5c6ee85a --- /dev/null +++ b/OFDFile/src/Content/GraphicUnit.cpp @@ -0,0 +1,108 @@ +#include "GraphicUnit.h" +#include "../../../OOXML/Base/Unit.h" + +namespace OFD +{ +CGraphicUnit::CGraphicUnit(CXmlReader& oLiteReader) + : m_bVisible(true), m_unDrawParam(0), m_dLineWidth(0.353), + m_eCap(ECap::Butt), m_eJoin(EJoin::Miter), m_dMiterLimit(4.234), + m_dDashOffset(0.), m_uchAlpha(255) +{ + if (0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return; + + std::wstring wsAttributeName; + + do + { + wsAttributeName = oLiteReader.GetName(); + + if (L"Boundary" == wsAttributeName) + m_oBoundary.Read(oLiteReader.GetTextA()); + else if (L"Name" == wsAttributeName) + m_wsName = oLiteReader.GetText(); + else if (L"Visible" == wsAttributeName) + m_bVisible = oLiteReader.GetBoolean(true); + else if (L"CTM" == wsAttributeName) + m_oCTM.Read(oLiteReader.GetTextA()); + else if (L"DrawParam" == wsAttributeName) + m_unDrawParam = oLiteReader.GetUInteger(true); + else if (L"LineWidth" == wsAttributeName) + m_dLineWidth = oLiteReader.GetDouble(true); + else if (L"Cap" == wsAttributeName) + { + const std::wstring wsValue{oLiteReader.GetText()}; + + if (L"Butt" == wsValue) + m_eCap = ECap::Butt; + else if (L"Round" == wsValue) + m_eCap = ECap::Round; + else if (L"Square" == wsValue) + m_eCap = ECap::Square; + } + else if (L"Join" == wsAttributeName) + { + const std::wstring wsValue{oLiteReader.GetText()}; + + if (L"Miter" == wsValue) + m_eJoin = EJoin::Miter; + else if (L"Round" == wsValue) + m_eJoin = EJoin::Round; + else if (L"Bevel" == wsValue) + m_eJoin = EJoin::Bevel; + } + else if (L"MiterLimit" == wsAttributeName) + m_dMiterLimit = oLiteReader.GetDouble(true); + else if (L"DashOffset" == wsAttributeName) + m_dDashOffset = oLiteReader.GetDouble(true); + else if (L"Alpha" == wsAttributeName) + m_uchAlpha = oLiteReader.GetUInteger(true); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); +} + +void CGraphicUnit::Apply(IRenderer* pRenderer, TMatrix& oOldTransform) const +{ + if (nullptr == pRenderer) + return; + + pRenderer->GetTransform(&oOldTransform.m_dM11, &oOldTransform.m_dM12, &oOldTransform.m_dM21, &oOldTransform.m_dM22, &oOldTransform.m_dDx, &oOldTransform.m_dDy); + + Aggplus::CMatrix oTransform(oOldTransform.m_dM11, oOldTransform.m_dM12, oOldTransform.m_dM21, oOldTransform.m_dM22, oOldTransform.m_dDx, oOldTransform.m_dDy); + const Aggplus::CMatrix oCurrentTransform(m_oCTM.m_dM11, m_oCTM.m_dM12, m_oCTM.m_dM21, m_oCTM.m_dM22, m_oBoundary.m_dX + m_oCTM.m_dDx, m_oBoundary.m_dY + m_oCTM.m_dDy); + + oTransform.Multiply(&oCurrentTransform); + + // Clipping + pRenderer->put_ClipMode(c_nClipRegionTypeWinding | c_nClipRegionIntersect); + + pRenderer->BeginCommand(c_nResetClipType); + pRenderer->EndCommand(c_nResetClipType); + + if (!m_oBoundary.Empty()) + { + pRenderer->BeginCommand(c_nClipType); + pRenderer->BeginCommand(c_nPathType); + pRenderer->PathCommandStart(); + + pRenderer->PathCommandMoveTo(m_oBoundary.m_dX, m_oBoundary.m_dY); + pRenderer->PathCommandLineTo(m_oBoundary.m_dX + m_oBoundary.m_dWidth, m_oBoundary.m_dY); + pRenderer->PathCommandLineTo(m_oBoundary.m_dX + m_oBoundary.m_dWidth, m_oBoundary.m_dY + m_oBoundary.m_dHeight); + pRenderer->PathCommandLineTo(m_oBoundary.m_dX, m_oBoundary.m_dY + m_oBoundary.m_dHeight); + pRenderer->PathCommandLineTo(m_oBoundary.m_dX, m_oBoundary.m_dY); + + pRenderer->EndCommand(c_nPathType); + pRenderer->EndCommand(c_nClipType); + pRenderer->PathCommandEnd(); + } + + pRenderer->SetTransform(oTransform.sx(), oTransform.shy(), oTransform.shx(), oTransform.sy(), oTransform.tx(), oTransform.ty()); +} + +TBox CGraphicUnit::GetBoundary() const +{ + return m_oBoundary; +} + +} diff --git a/OFDFile/src/Content/GraphicUnit.h b/OFDFile/src/Content/GraphicUnit.h new file mode 100644 index 0000000000..8cd10c6e5b --- /dev/null +++ b/OFDFile/src/Content/GraphicUnit.h @@ -0,0 +1,51 @@ +#ifndef GRAPHICUNIT_H +#define GRAPHICUNIT_H + +#include "../Utils/XmlReader.h" +#include "../Utils/Types.h" + +#include "../../../DesktopEditor/graphics/IRenderer.h" + +#include + +namespace OFD +{ +class CGraphicUnit +{ + TBox m_oBoundary; + std::wstring m_wsName; + bool m_bVisible; + TMatrix m_oCTM; + unsigned int m_unDrawParam; + double m_dLineWidth; + + enum class ECap + { + Butt, + Round, + Square + } m_eCap; + + enum class EJoin + { + Miter, + Round, + Bevel + } m_eJoin; + + double m_dMiterLimit; + double m_dDashOffset; + std::vector m_arDashPattern; + unsigned char m_uchAlpha; + + friend class CPathObject; +public: + CGraphicUnit(CXmlReader& oLiteReader); + + void Apply(IRenderer* pRenderer, TMatrix& oOldTransform) const; + + TBox GetBoundary() const; +}; +} + +#endif // GRAPHICUNIT_H diff --git a/OFDFile/src/Content/IPageBlock.h b/OFDFile/src/Content/IPageBlock.h new file mode 100644 index 0000000000..b89e62d139 --- /dev/null +++ b/OFDFile/src/Content/IPageBlock.h @@ -0,0 +1,21 @@ +#ifndef IPAGEBLOCK_H +#define IPAGEBLOCK_H + +#include "../IOFDElement.h" + +#include "../../../DesktopEditor/graphics/IRenderer.h" +#include "../Types/CommonData.h" + +namespace OFD +{ +class IPageBlock : public IOFDElement +{ +public: + IPageBlock(CXmlReader& oLiteReader) + : IOFDElement(oLiteReader){}; + virtual ~IPageBlock(){}; + virtual void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const = 0; +}; +} + +#endif // IPAGEBLOCK_H diff --git a/OFDFile/src/Content/ImageObject.cpp b/OFDFile/src/Content/ImageObject.cpp new file mode 100644 index 0000000000..4f0d7cfec1 --- /dev/null +++ b/OFDFile/src/Content/ImageObject.cpp @@ -0,0 +1,49 @@ +#include "ImageObject.h" + +namespace OFD +{ +CImageObject::CImageObject(CXmlReader& oLiteReader) + : IPageBlock(oLiteReader), CGraphicUnit(oLiteReader), m_unMultiMediaID(0) +{ + if ("ofd:ImageObject" != oLiteReader.GetNameA() || 0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return; + + std::string sAttributeName; + + do + { + sAttributeName = oLiteReader.GetNameA(); + + if ("ResourceID" == sAttributeName) + { + m_unMultiMediaID = oLiteReader.GetUInteger(true); + break; + } + } while(oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); +} + +void CImageObject::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer || nullptr == oCommonData.GetDocumentRes()) + return; + + const CMultiMedia* pMultiMedia = oCommonData.GetDocumentRes()->GetMultiMedia(m_unMultiMediaID); + + if (nullptr == pMultiMedia) + return; + + TMatrix oOldTransform; + CGraphicUnit::Apply(pRenderer, oOldTransform); + + const std::wstring wsFilePath = pMultiMedia->GetFilePath(); + + if (wsFilePath.empty()) + return; + + pRenderer->DrawImageFromFile(wsFilePath, 0, 0, 1, 1); + + pRenderer->SetTransform(oOldTransform.m_dM11, oOldTransform.m_dM12, oOldTransform.m_dM21, oOldTransform.m_dM22, oOldTransform.m_dDx, oOldTransform.m_dDy); +} +} diff --git a/OFDFile/src/Content/ImageObject.h b/OFDFile/src/Content/ImageObject.h new file mode 100644 index 0000000000..5ea978e188 --- /dev/null +++ b/OFDFile/src/Content/ImageObject.h @@ -0,0 +1,19 @@ +#ifndef IMAGEOBJECT_H +#define IMAGEOBJECT_H + +#include "IPageBlock.h" +#include "GraphicUnit.h" + +namespace OFD +{ +class CImageObject : public IPageBlock, public CGraphicUnit +{ + unsigned int m_unMultiMediaID; +public: + CImageObject(CXmlReader& oLiteReader); + + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const override; +}; +} + +#endif // IMAGEOBJECT_H diff --git a/OFDFile/src/Content/Layer.cpp b/OFDFile/src/Content/Layer.cpp new file mode 100644 index 0000000000..754ca81853 --- /dev/null +++ b/OFDFile/src/Content/Layer.cpp @@ -0,0 +1,32 @@ +#include "Layer.h" + +#include "../../../OOXML/Base/Unit.h" + +#include "PageBlock.h" + +namespace OFD +{ +CLayer::CLayer(CXmlReader& oLiteReader) + : IPageBlock(oLiteReader), m_eType(EType::Body) +{ + if (L"ofd:Layer" != oLiteReader.GetName()) + return; + + CPageBlock::ReadIntoContainer(oLiteReader, m_arPageBlocks); +} + +CLayer::~CLayer() +{ + for (IPageBlock* pPageBlock : m_arPageBlocks) + delete pPageBlock; +} + +void CLayer::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer) + return; + + for (const IPageBlock* pPageBlock : m_arPageBlocks) + pPageBlock->Draw(pRenderer, oCommonData); +} +} diff --git a/OFDFile/src/Content/Layer.h b/OFDFile/src/Content/Layer.h new file mode 100644 index 0000000000..4b913d2d61 --- /dev/null +++ b/OFDFile/src/Content/Layer.h @@ -0,0 +1,27 @@ +#ifndef LAYER_H +#define LAYER_H + +#include "IPageBlock.h" + +namespace OFD +{ +class CLayer : public IPageBlock +{ + enum class EType + { + Body, + Foreground, + Background + } m_eType; + + unsigned int m_unID; + std::vector m_arPageBlocks; +public: + CLayer(CXmlReader& oLiteReader); + ~CLayer(); + + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const override; +}; +} + +#endif // LAYER_H diff --git a/OFDFile/src/Content/PageBlock.cpp b/OFDFile/src/Content/PageBlock.cpp new file mode 100644 index 0000000000..c9daadd00f --- /dev/null +++ b/OFDFile/src/Content/PageBlock.cpp @@ -0,0 +1,52 @@ +#include "PageBlock.h" + +#include "TextObject.h" +#include "PathObject.h" +#include "ImageObject.h" + +namespace OFD +{ +CPageBlock::CPageBlock(CXmlReader& oLiteReader) + : IPageBlock(oLiteReader) +{ + if ("ofd:PageBlock" != oLiteReader.GetNameA() || oLiteReader.IsEmptyNode()) + return; + + CPageBlock::ReadIntoContainer(oLiteReader, m_arPageBlocks); +} + +void CPageBlock::ReadIntoContainer(CXmlReader& oLiteReader, std::vector& arPageBlocks) +{ + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + IPageBlock* pPageBlock = nullptr; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + pPageBlock = nullptr; + + if (L"ofd:TextObject" == wsNodeName) + pPageBlock = new CTextObject(oLiteReader); + else if (L"ofd:PathObject" == wsNodeName) + pPageBlock = new CPathObject(oLiteReader); + else if (L"ofd:PageBlock" == wsNodeName) + pPageBlock = new CPageBlock(oLiteReader); + else if (L"ofd:ImageObject" == wsNodeName) + pPageBlock = new CImageObject(oLiteReader); + + if (nullptr != pPageBlock) + arPageBlocks.push_back(pPageBlock); + } +} + +void CPageBlock::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer) + return; + + for (const IPageBlock* pPageBlock : m_arPageBlocks) + pPageBlock->Draw(pRenderer, oCommonData); +} +} diff --git a/OFDFile/src/Content/PageBlock.h b/OFDFile/src/Content/PageBlock.h new file mode 100644 index 0000000000..3a971b1e0a --- /dev/null +++ b/OFDFile/src/Content/PageBlock.h @@ -0,0 +1,21 @@ +#ifndef PAGEBLOCK_H +#define PAGEBLOCK_H + +#include "IPageBlock.h" +#include "../Res.h" + +namespace OFD +{ +class CPageBlock : public IPageBlock +{ + std::vector m_arPageBlocks; +public: + CPageBlock(CXmlReader& oLiteReader); + + static void ReadIntoContainer(CXmlReader& oLiteReader, std::vector& arPageBlocks); + + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const override; +}; +} + +#endif // PAGEBLOCK_H diff --git a/OFDFile/src/Content/PathObject.cpp b/OFDFile/src/Content/PathObject.cpp new file mode 100644 index 0000000000..8d850b1c28 --- /dev/null +++ b/OFDFile/src/Content/PathObject.cpp @@ -0,0 +1,392 @@ +#include "PathObject.h" +#include "src/Utils/Utils.h" + +namespace OFD +{ +CPathObject::CPathObject(CXmlReader& oLiteReader) + : IPageBlock(oLiteReader), CGraphicUnit(oLiteReader), + m_bStroke(true), m_bFill(false), m_eRule(ERule::NonZero), + m_pFillColor(nullptr), m_pStrokeColor(nullptr) +{ + if (L"ofd:PathObject" != oLiteReader.GetName() || oLiteReader.IsEmptyElement() || !oLiteReader.IsValid()) + return; + + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::wstring wsAttributeName; + + do + { + wsAttributeName = oLiteReader.GetName(); + + if (L"Stroke" == wsAttributeName) + m_bStroke = oLiteReader.GetBoolean(true); + else if (L"Fill" == wsAttributeName) + m_bFill = oLiteReader.GetBoolean(true); + else if (L"Rule" == wsAttributeName) + { + if (L"Even-odd" == oLiteReader.GetText()) + m_eRule = ERule::Even_Odd; + else + m_eRule = ERule::NonZero; + } + } while (oLiteReader.MoveToNextAttribute()); + } + + oLiteReader.MoveToElement(); + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:FillColor" == wsNodeName) + { + if (nullptr != m_pFillColor) + delete m_pFillColor; + + m_pFillColor = new CColor(oLiteReader); + } + else if (L"ofd:StrokeColor" == wsNodeName) + { + if (nullptr != m_pStrokeColor) + delete m_pStrokeColor; + + m_pStrokeColor = new CColor(oLiteReader); + } + else if (L"ofd:AbbreviatedData" == wsNodeName) + { + std::vector arValues{Split(oLiteReader.GetText2A(), ' ')}; + + std::vector::const_iterator itElement = arValues.cbegin(); + + char chElementName; + + while (arValues.cend() != itElement) + { + if (arValues.front().length() != 1) + { + ++itElement; + continue; + } + + chElementName = (*itElement)[0]; + ++itElement; + + switch (chElementName) + { + case 'S': + { + AddElement(CStartElement::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'M': + { + AddElement(CMoveElement::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'L': + { + AddElement(CLineElement::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'Q': + { + AddElement(CBezierCurve2Element::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'B': + { + AddElement(CBezierCurveElement::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'A': + { + AddElement(CArcElement::ReadFromArray(itElement, arValues.cend())); + break; + } + case 'C': + { + AddElement(new CCloseElement()); + break; + } + default: + continue; + } + } + } + } +} + +CPathObject::~CPathObject() +{ + for (const IPathElement* pElement : m_arElements) + delete pElement; +} + +void CPathObject::AddElement(const IPathElement* pElement) +{ + if (nullptr != pElement) + m_arElements.push_back(pElement); +} + +void CPathObject::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer || m_arElements.empty()) + return; + + TMatrix oOldTransform; + CGraphicUnit::Apply(pRenderer, oOldTransform); + + pRenderer->BeginCommand(c_nPathType); + pRenderer->PathCommandStart(); + + for (const IPathElement* pElement : m_arElements) + pElement->Draw(pRenderer); + + int nEndType = -1; + + if (m_bStroke) + nEndType = c_nStroke; + + if (m_bFill) + { + switch (m_eRule) + { + case ERule::NonZero: + { + nEndType = (-1 == nEndType ? c_nWindingFillMode : nEndType | c_nWindingFillMode); + break; + } + case ERule::Even_Odd: + { + nEndType = (-1 == nEndType ? c_nEvenOddFillMode : nEndType | c_nEvenOddFillMode); + break; + } + } + } + + if (m_bFill) + { + pRenderer->put_BrushType(c_BrushTypeSolid); + + if (nullptr != m_pFillColor) + { + pRenderer->put_BrushColor1(m_pFillColor->ToInt(oCommonData.GetPublicRes())); + pRenderer->put_BrushAlpha1(m_pFillColor->GetAlpha()); + } + else + { + pRenderer->put_BrushColor1(0); + pRenderer->put_BrushAlpha1(0xff); + } + } + else + pRenderer->put_BrushType(c_BrushTypeNotSet); + + + if(m_bStroke) + { + pRenderer->put_PenSize(m_dLineWidth); + + if (nullptr != m_pStrokeColor) + { + pRenderer->put_PenColor(m_pStrokeColor->ToInt(oCommonData.GetPublicRes())); + pRenderer->put_PenAlpha(m_pStrokeColor->GetAlpha()); + } + else + { + pRenderer->put_PenColor(0); + pRenderer->put_PenAlpha(0xff); + } + } + else + pRenderer->put_PenSize(0.); + + if (-1 != nEndType) + pRenderer->DrawPath(nEndType); + + pRenderer->PathCommandEnd(); + pRenderer->EndCommand(c_nPathType); + + pRenderer->SetTransform(oOldTransform.m_dM11, oOldTransform.m_dM12, oOldTransform.m_dM21, oOldTransform.m_dM22, oOldTransform.m_dDx, oOldTransform.m_dDy); +} + +CStartElement::CStartElement() +{} + +IPathElement* CStartElement::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + if (itEnd - itBegin < 2) + return nullptr; + + CStartElement *pElement = new CStartElement(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble(*itBegin++, pElement->m_dX) && StringToDouble(*itBegin++, pElement->m_dY)) + return pElement; + + delete pElement; + return nullptr; +} + +void CStartElement::Draw(IRenderer* pRenderer) const +{ + if (nullptr != pRenderer) + pRenderer->PathCommandMoveTo(m_dX, m_dY); +} + +CMoveElement::CMoveElement() +{} + +IPathElement* CMoveElement::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + if (itEnd - itBegin < 2) + return nullptr; + + CMoveElement *pElement = new CMoveElement(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble(*itBegin++, pElement->m_dX) && StringToDouble(*itBegin++, pElement->m_dY)) + return pElement; + + delete pElement; + return nullptr; +} + +void CMoveElement::Draw(IRenderer* pRenderer) const +{ + if (nullptr != pRenderer) + pRenderer->PathCommandMoveTo(m_dX, m_dY); +} + +CLineElement::CLineElement() +{} + +IPathElement* CLineElement::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + if (itEnd - itBegin < 2) + return nullptr; + + CLineElement *pElement = new CLineElement(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble(*itBegin++, pElement->m_dX) && StringToDouble(*itBegin++, pElement->m_dY)) + return pElement; + + delete pElement; + return nullptr; +} + +void CLineElement::Draw(IRenderer* pRenderer) const +{ + if (nullptr != pRenderer) + pRenderer->PathCommandLineTo(m_dX, m_dY); +} + +CBezierCurve2Element::CBezierCurve2Element() +{} + +IPathElement* CBezierCurve2Element::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + if (itEnd - itBegin < 4) + return nullptr; + + CBezierCurve2Element *pElement = new CBezierCurve2Element(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble(*itBegin++, pElement->m_dX1) && StringToDouble(*itBegin++, pElement->m_dY1) && + StringToDouble(*itBegin++, pElement->m_dX2) && StringToDouble(*itBegin++, pElement->m_dY2)) + return pElement; + + delete pElement; + return nullptr; +} + +void CBezierCurve2Element::Draw(IRenderer* pRenderer) const +{ + if (nullptr == pRenderer) + return; + + double dX = 0, dY = 0; + pRenderer->PathCommandGetCurrentPoint(&dX, &dY); + pRenderer->PathCommandCurveTo(dX, dY, m_dX1, m_dY1, m_dX2, m_dY2); +} + +CBezierCurveElement::CBezierCurveElement() +{} + +IPathElement* CBezierCurveElement::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + if (itEnd - itBegin < 6) + return nullptr; + + CBezierCurveElement *pElement = new CBezierCurveElement(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble(*itBegin++, pElement->m_dX1) && StringToDouble(*itBegin++, pElement->m_dY1) && + StringToDouble(*itBegin++, pElement->m_dX2) && StringToDouble(*itBegin++, pElement->m_dY2) && + StringToDouble(*itBegin++, pElement->m_dX3) && StringToDouble(*itBegin++, pElement->m_dY3)) + return pElement; + + delete pElement; + return nullptr; +} + +void CBezierCurveElement::Draw(IRenderer* pRenderer) const +{ + if (nullptr != pRenderer) + pRenderer->PathCommandCurveTo(m_dX1, m_dY1, m_dX2, m_dY2, m_dX3, m_dY3); +} + +CArcElement::CArcElement() +{} + +IPathElement* CArcElement::ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd) +{ + + if (itEnd - itBegin < 7) + return nullptr; + + CArcElement *pElement = new CArcElement(); + + if (nullptr == pElement) + return nullptr; + + if (StringToDouble (*itBegin++, pElement->m_dRadiusX) && StringToDouble (*itBegin++, pElement->m_dRadiusY) && + StringToDouble (*itBegin++, pElement->m_dAngle) && StringToBoolean(*itBegin++, pElement->m_bLarge) && + StringToBoolean(*itBegin++, pElement->m_bSweep) && StringToDouble (*itBegin++, pElement->m_dX) && + StringToDouble (*itBegin++, pElement->m_dY)) + return pElement; + + delete pElement; + return nullptr; +} + +void CArcElement::Draw(IRenderer* pRenderer) const +{ + // if (nullptr != pRenderer) + // pRenderer->PathCommandArcTo(m_dX, m_dY, m_dRadiusX * 2., m_dRadiusY * 2., ) +} + +CCloseElement::CCloseElement() +{} + +void CCloseElement::Draw(IRenderer* pRenderer) const +{ + if (nullptr != pRenderer) + pRenderer->PathCommandClose(); +} +} diff --git a/OFDFile/src/Content/PathObject.h b/OFDFile/src/Content/PathObject.h new file mode 100644 index 0000000000..4a11d9fea7 --- /dev/null +++ b/OFDFile/src/Content/PathObject.h @@ -0,0 +1,124 @@ +#ifndef PATHOBJECT_H +#define PATHOBJECT_H + +#include "IPageBlock.h" +#include "GraphicUnit.h" + +#include "../Types/Color.h" + +namespace OFD +{ +class IPathElement +{ +public: + IPathElement(){}; + virtual ~IPathElement(){}; + + static IPathElement* ReadFromArray(std::vector& arValues) { return nullptr; }; + virtual void Draw(IRenderer* pRenderer) const = 0; +}; + +class CStartElement : public IPathElement +{ + double m_dX; + double m_dY; +public: + CStartElement(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CMoveElement : public IPathElement +{ + double m_dX; + double m_dY; +public: + CMoveElement(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CLineElement : public IPathElement +{ + double m_dX; + double m_dY; +public: + CLineElement(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CBezierCurve2Element : public IPathElement +{ + double m_dX1; + double m_dY1; + double m_dX2; + double m_dY2; +public: + CBezierCurve2Element(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CBezierCurveElement : public IPathElement +{ + double m_dX1; + double m_dY1; + double m_dX2; + double m_dY2; + double m_dX3; + double m_dY3; +public: + CBezierCurveElement(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CArcElement : public IPathElement +{ + double m_dRadiusX; + double m_dRadiusY; + double m_dAngle; + bool m_bLarge; + bool m_bSweep; + double m_dX; + double m_dY; +public: + CArcElement(); + static IPathElement* ReadFromArray(std::vector::const_iterator& itBegin, const std::vector::const_iterator& itEnd); + void Draw(IRenderer* pRenderer) const override; +}; + +class CCloseElement : public IPathElement +{ +public: + CCloseElement(); + void Draw(IRenderer* pRenderer) const override; +}; + +class CPathObject : public IPageBlock, public CGraphicUnit +{ + bool m_bStroke; + bool m_bFill; + + enum class ERule + { + NonZero, + Even_Odd + } m_eRule; + + CColor* m_pFillColor; + CColor* m_pStrokeColor; + + std::vector m_arElements; + + void AddElement(const IPathElement* pElement); +public: + CPathObject(CXmlReader& oLiteReader); + ~CPathObject(); + + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const override; +}; +} + +#endif // PATHOBJECT_H diff --git a/OFDFile/src/Content/TextObject.cpp b/OFDFile/src/Content/TextObject.cpp new file mode 100644 index 0000000000..1239bedb67 --- /dev/null +++ b/OFDFile/src/Content/TextObject.cpp @@ -0,0 +1,277 @@ +#include "TextObject.h" + +#include "../Utils/Utils.h" + +namespace OFD +{ +CTextCode::CTextCode(CXmlReader& oLiteReader) +{ + if (L"ofd:TextCode" != oLiteReader.GetName() || oLiteReader.IsEmptyElement() || !oLiteReader.IsValid()) + return; + + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::wstring wsAttributeName; + + do + { + wsAttributeName = oLiteReader.GetName(); + + if (L"X" == wsAttributeName) + m_dX = oLiteReader.GetDouble(true); + else if (L"Y" == wsAttributeName) + m_dY = oLiteReader.GetDouble(true); + else if (L"DeltaX" == wsAttributeName || + L"DeltaY" == wsAttributeName) + { + const std::vector arValues{oLiteReader.GetArrayStrings(true)}; + + std::vector& arDelta{L"DeltaX" == wsAttributeName ? m_arDeltaX : m_arDeltaY}; + + arDelta.reserve(arValues.size()); + double dValue = 0.; + + for (unsigned int unIndex = 0; unIndex < arValues.size(); ++unIndex) + { + if ("g" == arValues[unIndex] && unIndex + 2 < arValues.size()) + { + unsigned int unCount = 0; + + if (!StringToUInteger(arValues[unIndex + 1], unCount) || !StringToDouble(arValues[unIndex + 2], dValue)) + continue; + + unIndex += 2; + + arDelta.insert(arDelta.end(), unCount, dValue); + } + else if (StringToDouble(arValues[unIndex], dValue)) + arDelta.push_back(dValue); + else + arDelta.push_back(0.); + } + } + } while (oLiteReader.MoveToNextAttribute()); + } + + oLiteReader.MoveToElement(); + + m_wsText = oLiteReader.GetText2(); +} + +void CTextCode::Draw(IRenderer* pRenderer, unsigned int& unIndex, const std::vector& arCGTransforms) const +{ + if (nullptr == pRenderer || m_wsText.empty()) + return; + + double dX = m_dX, dY = m_dY, dDeltaX = 0, dDeltaY = 0; + bool bDrawed = false; + + for (unsigned int unGlyphIndex = 0; unGlyphIndex < m_wsText.length(); ++unGlyphIndex) + { + if (!arCGTransforms.empty()) + { + for (const TCGTransform& oCGTransform : arCGTransforms) + { + if (oCGTransform.Draw(pRenderer, m_wsText[unGlyphIndex], unIndex, dX, dY)) + { + bDrawed = true; + break; + } + } + } + + if (!bDrawed) + { + pRenderer->CommandDrawTextCHAR(m_wsText[unGlyphIndex], dX, dY, 0, 0); + ++unIndex; + } + + if (unGlyphIndex < m_arDeltaX.size()) + dDeltaX = m_arDeltaX[unGlyphIndex]; + + if (unGlyphIndex < m_arDeltaY.size()) + dDeltaY = m_arDeltaY[unGlyphIndex]; + + dX += dDeltaX; + dY += dDeltaY; + } +} + +CTextObject::CTextObject(CXmlReader& oLiteReader) + : IPageBlock(oLiteReader), CGraphicUnit(oLiteReader), + m_bStroke(false), m_bFill(true), m_dHScale(1.), + m_unReadDirection(0), m_unCharDirection(0), m_unWeight(400), + m_bItalic(false), + m_pFillColor(nullptr), m_pStrokeColor(nullptr), m_unFontID(0) +{ + if (L"ofd:TextObject" != oLiteReader.GetName() || oLiteReader.IsEmptyElement() || !oLiteReader.IsValid()) + return; + + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::wstring wsAttributeName; + + do + { + wsAttributeName = oLiteReader.GetName(); + + if (L"Font" == wsAttributeName) + m_unFontID = oLiteReader.GetUInteger(true); + else if (L"Size" == wsAttributeName) + m_dSize = oLiteReader.GetDouble(true); + else if (L"Stroke" == wsAttributeName) + m_bStroke = oLiteReader.GetBoolean(true); + else if (L"Fill" == wsAttributeName) + m_bFill = oLiteReader.GetBoolean(true); + else if (L"HScale" == wsAttributeName) + m_dHScale = oLiteReader.GetDouble(true); + else if (L"ReadDirection" == wsAttributeName) + m_unReadDirection = oLiteReader.GetUInteger(true); + else if (L"CharDirection" == wsAttributeName) + m_unCharDirection =oLiteReader.GetUInteger(true); + else if (L"Weight" == wsAttributeName) + m_unWeight = oLiteReader.GetUInteger(true); + else if (L"Italic" == wsAttributeName) + m_bItalic = oLiteReader.GetBoolean(true); + } while (oLiteReader.MoveToNextAttribute()); + } + + oLiteReader.MoveToElement(); + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:FillColor" == wsNodeName) + { + if (nullptr != m_pFillColor) + delete m_pFillColor; + + m_pFillColor = new CColor(oLiteReader); + } + else if (L"ofd:StrokeColor" == wsNodeName) + { + if (nullptr != m_pStrokeColor) + delete m_pStrokeColor; + + m_pStrokeColor = new CColor(oLiteReader); + } + else if (L"ofd:TextCode" == wsNodeName) + m_arTextCodes.push_back(new CTextCode(oLiteReader)); + else if (L"ofd:CGTransform" == wsNodeName) + m_arCGTransforms.push_back(TCGTransform::Read(oLiteReader)); + } +} + +CTextObject::~CTextObject() +{ + if (nullptr != m_pFillColor) + delete m_pFillColor; + + if (nullptr != m_pStrokeColor) + delete m_pStrokeColor; + + for (const CTextCode* pTextCode : m_arTextCodes) + delete pTextCode; +} + +void CTextObject::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer || m_arTextCodes.empty()) + return; + + const CFont* pFont = oCommonData.GetPublicRes()->GetFont(m_unFontID); + + if (nullptr == pFont) + return; + + pFont->Apply(pRenderer); + + TMatrix oOldTransform; + CGraphicUnit::Apply(pRenderer, oOldTransform); + + if (m_bFill) + { + pRenderer->put_BrushType(c_BrushTypeSolid); + + if (nullptr != m_pFillColor) + { + pRenderer->put_BrushColor1(m_pFillColor->ToInt(oCommonData.GetPublicRes())); + pRenderer->put_BrushAlpha1(m_pFillColor->GetAlpha()); + } + else + { + pRenderer->put_BrushColor1(0); + pRenderer->put_BrushAlpha1(0xff); + } + } + else + pRenderer->put_BrushType(c_BrushTypeNotSet); + + pRenderer->put_FontSize(m_dSize * 72. / 25.4); + + unsigned int unGlyphsIndex = 0; + + for (const CTextCode* pTextCode : m_arTextCodes) + pTextCode->Draw(pRenderer, unGlyphsIndex, m_arCGTransforms); + + pRenderer->SetTransform(oOldTransform.m_dM11, oOldTransform.m_dM12, oOldTransform.m_dM21, oOldTransform.m_dM22, oOldTransform.m_dDx, oOldTransform.m_dDy); +} + +TCGTransform TCGTransform::Read(CXmlReader& oLiteReader) +{ + TCGTransform oCGTransform; + + if (L"ofd:CGTransform" != oLiteReader.GetName() || oLiteReader.IsEmptyElement()) + return oCGTransform; + + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::wstring wsAttributeName; + + do + { + wsAttributeName = oLiteReader.GetName(); + + if (L"CodePosition" == wsAttributeName) + oCGTransform.m_unCodePosition = oLiteReader.GetUInteger(true); + else if (L"CodeCount" == wsAttributeName) + oCGTransform.m_unCodeCount = oLiteReader.GetUInteger(true); + else if (L"GlyphCount" == wsAttributeName) + oCGTransform.m_unGlyphCount = oLiteReader.GetUInteger(true); + } while (oLiteReader.MoveToNextAttribute()); + } + + oLiteReader.MoveToElement(); + + const int nDepth = oLiteReader.GetDepth(); + unsigned int unCount = 0; + + while (oLiteReader.ReadNextSiblingNode(nDepth) && unCount < oCGTransform.m_unGlyphCount) + { + if ("ofd:Glyphs" == oLiteReader.GetNameA()) + { + oCGTransform.m_arGlyphs.push_back(oLiteReader.GetUInteger()); + ++unCount; + } + } + + return oCGTransform; +} + +bool TCGTransform::Draw(IRenderer* pRenderer, const LONG& lUnicode, unsigned int& unIndex, double dX, double dY) const +{ + if (m_unCodePosition != unIndex || 0 == m_unCodeCount || 0 == m_unGlyphCount) + return false; + + for (unsigned int unGlyphCount = 0; unGlyphCount < m_unGlyphCount; ++unGlyphCount) + pRenderer->CommandDrawTextExCHAR(lUnicode, m_arGlyphs[unGlyphCount], dX, dY, 0, 0); + + unIndex += m_unCodeCount; + + return true; +} +} diff --git a/OFDFile/src/Content/TextObject.h b/OFDFile/src/Content/TextObject.h new file mode 100644 index 0000000000..1b01d57d42 --- /dev/null +++ b/OFDFile/src/Content/TextObject.h @@ -0,0 +1,65 @@ +#ifndef TEXTOBJECT_H +#define TEXTOBJECT_H + +#include "IPageBlock.h" +#include "GraphicUnit.h" + +#include "../Types/Color.h" + +namespace OFD +{ +struct TCGTransform +{ + unsigned int m_unCodePosition; + unsigned int m_unCodeCount; + unsigned int m_unGlyphCount; + + std::vector m_arGlyphs; + + static TCGTransform Read(CXmlReader& oLiteReader); + + bool Draw(IRenderer* pRenderer, const LONG& lUnicode, unsigned int& unIndex, double dX, double dY) const; +}; + +class CTextCode +{ + double m_dX; + double m_dY; + + std::vector m_arDeltaX; + std::vector m_arDeltaY; + + std::wstring m_wsText; +public: + CTextCode(CXmlReader& oLiteReader); + + void Draw(IRenderer* pRenderer, unsigned int& unIndex, const std::vector& arCGTransforms) const; +}; + +class CTextObject : public IPageBlock, public CGraphicUnit +{ + double m_dSize; + bool m_bStroke; + bool m_bFill; + double m_dHScale; + unsigned int m_unReadDirection; + unsigned int m_unCharDirection; + unsigned int m_unWeight; + bool m_bItalic; + + CColor* m_pFillColor; + CColor* m_pStrokeColor; + + unsigned int m_unFontID; + + std::vector m_arTextCodes; + std::vector m_arCGTransforms; +public: + CTextObject(CXmlReader& oLiteReader); + ~CTextObject(); + + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const override; +}; +} + +#endif // TEXTOBJECT_H diff --git a/OFDFile/src/Document.cpp b/OFDFile/src/Document.cpp new file mode 100644 index 0000000000..272bcbce7f --- /dev/null +++ b/OFDFile/src/Document.cpp @@ -0,0 +1,142 @@ +#include "Document.h" + +#include "Utils/Utils.h" + +#include "../../DesktopEditor/common/Path.h" + +namespace OFD +{ +CPermission::CPermission() + : m_bEdit(true), m_bAnnot(true), m_bExport(true), + m_bSignature(true), m_bWatermark(true), m_bPrintScreen(true) +{} + +bool CPermission::Read(CXmlReader& oLiteReader) +{ + if (L"ofd:Permission" != oLiteReader.GetName()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:Edit" == wsNodeName) + m_bEdit = oLiteReader.GetBoolean(); + } + + return true; +} + +CDocument::CDocument() +{} + +CDocument::~CDocument() +{ + for (std::pair oElement : m_mPages) + delete oElement.second; +} + +bool CDocument::Empty() const +{ + return m_mPages.empty(); +} + +bool CDocument::Read(const std::wstring& wsFilePath, IFolder* pFolder) +{ + if (wsFilePath.empty() || !CanUseThisPath(wsFilePath, pFolder->getFullFilePath(L""))) + return false; + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(pFolder->getFullFilePath(wsFilePath)) || !oLiteReader.ReadNextNode() || L"ofd:Document" != oLiteReader.GetName()) + return false; + + const std::wstring wsCoreDirectory{pFolder->getFullFilePath(NSSystemPath::GetDirectoryName(wsFilePath))}; + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:CommonData" == wsNodeName) + m_oCommonData.Read(oLiteReader, wsCoreDirectory); + else if (L"ofd:Pages" == wsNodeName) + { + const int nPagesDepth = oLiteReader.GetDepth(); + + int nID = -1; + std::wstring wsBaseLoc; + + + while (oLiteReader.ReadNextSiblingNode(nPagesDepth)) + { + if (L"ofd:Page" != oLiteReader.GetName() || 2 > oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + continue; + + do + { + if (L"ID" == oLiteReader.GetName()) + nID = oLiteReader.GetInteger(true); + else if (L"BaseLoc" == oLiteReader.GetName()) + wsBaseLoc = oLiteReader.GetText(); + }while (oLiteReader.MoveToNextAttribute()); + + if (wsBaseLoc.empty()) + continue; + + if (-1 == nID) + nID = m_mPages.size() + 1; + + CPage* pPage = CPage::Read(wsBaseLoc, wsCoreDirectory); + + if (nullptr != pPage) + m_mPages.insert(std::make_pair(m_mPages.size(), pPage)); + + wsBaseLoc.clear(); + oLiteReader.MoveToElement(); + } + } + else if (L"ofd:Permissions" == wsNodeName) + m_oPermission.Read(oLiteReader); + } + + return false; +} + +bool CDocument::DrawPage(IRenderer* pRenderer, int nPageIndex) const +{ + if (nullptr == pRenderer) + return false; + + std::map::const_iterator itFound = m_mPages.find(nPageIndex); + + if (itFound == m_mPages.cend()) + return false; + + itFound->second->Draw(pRenderer, m_oCommonData); + + return true; +} + +unsigned int CDocument::GetPageCount() const +{ + return m_mPages.size(); +} + +bool CDocument::GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const +{ + m_oCommonData.GetPageSize(dWidth, dHeight); + + std::map::const_iterator itFound = m_mPages.find(nPageIndex); + + if (itFound == m_mPages.cend()) + return false; + + itFound->second->GetPageSize(dWidth, dHeight); + + return true; +} +} diff --git a/OFDFile/src/Document.h b/OFDFile/src/Document.h new file mode 100644 index 0000000000..ee7f265c77 --- /dev/null +++ b/OFDFile/src/Document.h @@ -0,0 +1,46 @@ +#ifndef DOCUMENT_H +#define DOCUMENT_H + +#include "Page.h" + +#include "../../DesktopEditor/graphics/IRenderer.h" +#include "../../OfficeUtils/src/ZipFolder.h" + +namespace OFD +{ +class CPermission +{ + bool m_bEdit; + bool m_bAnnot; + bool m_bExport; + bool m_bSignature; + bool m_bWatermark; + bool m_bPrintScreen; +public: + CPermission(); + + bool Read(CXmlReader& oLiteReader); +}; + +class CDocument +{ + CCommonData m_oCommonData; + CPermission m_oPermission; + + std::map m_mPages; +public: + CDocument(); + ~CDocument(); + + bool Empty() const; + + bool Read(const std::wstring& wsFilePath, IFolder* pFolder); + + bool DrawPage(IRenderer* pRenderer, int nPageIndex) const; + + unsigned int GetPageCount() const; + bool GetPageSize(int nPageIndex, double& dWidth, double &dHeight) const; +}; +} + +#endif // DOCUMENT_H diff --git a/OFDFile/src/IOFDElement.h b/OFDFile/src/IOFDElement.h new file mode 100644 index 0000000000..6ea49d4662 --- /dev/null +++ b/OFDFile/src/IOFDElement.h @@ -0,0 +1,35 @@ +#ifndef IOFDELEMENT_H +#define IOFDELEMENT_H + +#include "Utils/XmlReader.h" + +namespace OFD +{ +class IOFDElement +{ + unsigned int m_unID; +public: + IOFDElement(CXmlReader& oLiteReader) + : m_unID(0) + { + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + do + { + if (L"ID" == oLiteReader.GetName()) + m_unID = oLiteReader.GetUInteger(true); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); + } + }; + virtual ~IOFDElement(){}; + + unsigned int GetID() const + { + return m_unID; + } +}; +} + +#endif // IOFDELEMENT_H diff --git a/OFDFile/src/OFDFile_Private.cpp b/OFDFile/src/OFDFile_Private.cpp new file mode 100644 index 0000000000..0e1a66bb6b --- /dev/null +++ b/OFDFile/src/OFDFile_Private.cpp @@ -0,0 +1,140 @@ +#include "OFDFile_Private.h" + +#include "../../OfficeUtils/src/OfficeUtils.h" +#include "Utils/Utils.h" + +COFDFile_Private::COFDFile_Private(NSFonts::IApplicationFonts* pFonts) + : m_pAppFonts(pFonts), m_pFontManager(nullptr), m_pTempFolder(nullptr) +{ + if (nullptr == pFonts) + return; + + // Создаем менеджер шрифтов с собственным кэшем + m_pFontManager = pFonts->GenerateFontManager(); + NSFonts::IFontsCache* pMeasurerCache = NSFonts::NSFontCache::Create(); + pMeasurerCache->SetStreams(pFonts->GetStreams()); + m_pFontManager->SetOwnerCache(pMeasurerCache); + pMeasurerCache->SetCacheSize(16); +} + +COFDFile_Private::~COFDFile_Private() +{ + Close(); + + if (nullptr != m_pTempFolder) + delete m_pTempFolder; + + RELEASEINTERFACE(m_pFontManager); +} + +void COFDFile_Private::Close() +{} + +void COFDFile_Private::SetTempDir(const std::wstring& wsPath) +{ + if (nullptr != m_pTempFolder) + delete m_pTempFolder; + + if (!NSDirectory::Exists(wsPath)) + NSDirectory::CreateDirectory(wsPath); + + int nCounter = 0; + std::wstring wsTempFolder = wsPath + L"/OFD/"; + + while (NSDirectory::Exists(wsTempFolder)) + { + wsTempFolder = wsPath + L"/OFD" + std::to_wstring(nCounter) + L'/'; + nCounter++; + } + + NSDirectory::CreateDirectory(wsTempFolder); + + m_pTempFolder = new CFolderSystem(wsTempFolder); +} + +std::wstring COFDFile_Private::GetTempDir() const +{ + return (nullptr != m_pTempFolder) ? m_pTempFolder->getFullFilePath(L"") : std::wstring(); +} + +bool COFDFile_Private::Read(IFolder* pFolder) +{ + if (nullptr == pFolder) + return false; + + return m_oBase.Read(pFolder); +} + +bool COFDFile_Private::LoadFromFile(const std::wstring& wsFilePath) +{ + if (wsFilePath.empty() || nullptr == m_pTempFolder) + return false; + + Close(); + + COfficeUtils oUtils(NULL); + + if (S_OK != oUtils.ExtractToDirectory(wsFilePath, m_pTempFolder->getFullFilePath(L""), NULL, 0)) + return false; + + return Read(m_pTempFolder); +} + +bool COFDFile_Private::LoadFromMemory(BYTE* pData, DWORD ulLength) +{ + Close(); + + if (nullptr != m_pTempFolder) + delete m_pTempFolder; + + m_pTempFolder = new CZipFolderMemory(pData, ulLength); + + return Read(m_pTempFolder); +} + +unsigned int COFDFile_Private::GetPageCount() const +{ + return m_oBase.GetPageCount(); +} + +void COFDFile_Private::GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const +{ + m_oBase.GetPageSize(nPageIndex, dWidth, dHeight); +} + +void COFDFile_Private::DrawPage(IRenderer* pRenderer, int nPageIndex) +{ + m_oBase.DrawPage(pRenderer, nPageIndex); +} + +void COFDFile_Private::DrawPage(IRenderer* pRenderer, int nPageIndex, const double& dX, const double& dY, const double& dWidth, const double& dHeight) +{ + if (nullptr == pRenderer) + return; + + double dPageWidth = 0., dPageHeight = 0.; + + GetPageSize(nPageIndex, dPageWidth, dPageHeight); + + if (OFD::IsZeroValue(dPageWidth) || OFD::IsZeroValue(dPageHeight)) + return; + + double dM11, dM12, dM21, dM22, dDx, dDy; + pRenderer->GetTransform(&dM11, &dM12, &dM21, &dM22, &dDx, &dDy); + + Aggplus::CMatrix oTransform(dM11, dM12, dM21, dM22, dDx, dDy); + + oTransform.Scale(dWidth / dPageWidth, dHeight / dPageHeight); + oTransform.Translate(dX, dY); + + pRenderer->SetTransform(oTransform.sx(), oTransform.shy(), oTransform.shx(), oTransform.sy(), oTransform.tx(), oTransform.ty()); + + m_oBase.DrawPage(pRenderer, nPageIndex); + + pRenderer->SetTransform(dM11, dM12, dM21, dM22, dDx, dDy); +} + +NSFonts::IApplicationFonts* COFDFile_Private::GetFonts() +{ + return m_pAppFonts; +} diff --git a/OFDFile/src/OFDFile_Private.h b/OFDFile/src/OFDFile_Private.h new file mode 100644 index 0000000000..1f7d0a79fc --- /dev/null +++ b/OFDFile/src/OFDFile_Private.h @@ -0,0 +1,41 @@ +#ifndef OFDFILE_PRIVATE_H +#define OFDFILE_PRIVATE_H + +#include "../../OfficeUtils/src/ZipFolder.h" + +#include "../../DesktopEditor/graphics/IRenderer.h" +#include "../../DesktopEditor/graphics/pro/Fonts.h" + +#include "Base.h" + +class COFDFile_Private +{ + NSFonts::IApplicationFonts* m_pAppFonts; + NSFonts::IFontManager* m_pFontManager; + IFolder* m_pTempFolder; + + OFD::CBase m_oBase; + + bool Read(IFolder* pFolder); +public: + COFDFile_Private(NSFonts::IApplicationFonts* pFonts); + ~COFDFile_Private(); + + void Close(); + + void SetTempDir(const std::wstring& wsPath); + std::wstring GetTempDir() const; + + bool LoadFromFile(const std::wstring& wsFilePath); + bool LoadFromMemory(BYTE* pData, DWORD ulLength); + + unsigned int GetPageCount() const; + void GetPageSize(int nPageIndex, double& dWidth, double& dHeight) const; + + void DrawPage(IRenderer* pRenderer, int nPageIndex); + void DrawPage(IRenderer* pRenderer, int nPageIndex, const double& dX, const double& dY, const double& dWidth, const double& dHeight); + + NSFonts::IApplicationFonts* GetFonts(); +}; + +#endif // OFDFILE_PRIVATE_H diff --git a/OFDFile/src/Page.cpp b/OFDFile/src/Page.cpp new file mode 100644 index 0000000000..34a47a28c4 --- /dev/null +++ b/OFDFile/src/Page.cpp @@ -0,0 +1,94 @@ +#include "Page.h" + +#include "Utils/Utils.h" + +#include "../../DesktopEditor/common/File.h" + +namespace OFD +{ +CPage::CPage() + : m_parTemplatePage{0, EZOrder::Background} +{} + +CPage::~CPage() +{} + +CPage* CPage::Read(const std::wstring& wsFilePath, const std::wstring& wsRootPath) +{ + if (wsFilePath.empty() || !CanUseThisPath(wsFilePath, wsRootPath)) + return nullptr; + + std::wstring wsNormalizedPath = CombinePaths(wsRootPath, wsFilePath); + + if (L"xml" != NSFile::GetFileExtention(wsNormalizedPath)) + wsNormalizedPath = CombinePaths(wsNormalizedPath, L"Content.xml"); + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(wsNormalizedPath) || !oLiteReader.ReadNextNode() || L"ofd:Page" != oLiteReader.GetName()) + return nullptr; + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + CPage *pPage = new CPage(); + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:Content" == wsNodeName) + pPage->m_oContent.Read(oLiteReader); + else if (L"ofd:Area" == wsNodeName) + pPage->m_oArea.Read(oLiteReader); + else if (L"ofd:Template" == wsNodeName && 0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::string sAttributeName; + + do + { + sAttributeName = oLiteReader.GetNameA(); + + if ("ZOrder" == sAttributeName) + pPage->m_parTemplatePage.second = GetZOrderFromString(oLiteReader.GetTextA()); + else if ("TemplateID" == sAttributeName) + pPage->m_parTemplatePage.first = oLiteReader.GetUInteger(true); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); + } + } + + return pPage; +} + +void CPage::Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const +{ + if (nullptr == pRenderer) + return; + + pRenderer->BeginCommand(c_nImageType); + + if (0 != m_parTemplatePage.first) + { + const CTemplatePage *pTemplatePage = oCommonData.GetTemplatePage(m_parTemplatePage.first, m_parTemplatePage.second); + + if (nullptr != pTemplatePage && EZOrder::Background == pTemplatePage->GetZOrder() && nullptr != pTemplatePage->GetPage()) + pTemplatePage->GetPage()->Draw(pRenderer, oCommonData); + } + + m_oContent.Draw(pRenderer, oCommonData); + + pRenderer->EndCommand(c_nImageType); +} + +void CPage::GetPageSize(double& dWidth, double& dHeight) const +{ + TBox oPhysicalBox{m_oArea.GetPhysicalBox()}; + + if (oPhysicalBox.Empty()) + return; + + dWidth = oPhysicalBox.m_dWidth; + dHeight = oPhysicalBox.m_dHeight; +} +} diff --git a/OFDFile/src/Page.h b/OFDFile/src/Page.h new file mode 100644 index 0000000000..09d16e5130 --- /dev/null +++ b/OFDFile/src/Page.h @@ -0,0 +1,27 @@ +#ifndef PAGE_H +#define PAGE_H + +#include "Content/Content.h" +#include "Types/CommonData.h" +#include "Types/TemplatePage.h" + +namespace OFD +{ +class CPage +{ + CPageArea m_oArea; + CContent m_oContent; + + std::pair m_parTemplatePage; +public: + CPage(); + ~CPage(); + + static CPage* Read(const std::wstring& wsFilePath, const std::wstring& wsRootPath); + void Draw(IRenderer* pRenderer, const CCommonData& oCommonData) const; + + void GetPageSize(double& dWidth, double& dHeight) const; +}; +} + +#endif // PAGE_H diff --git a/OFDFile/src/Res.cpp b/OFDFile/src/Res.cpp new file mode 100644 index 0000000000..6ad11a11a9 --- /dev/null +++ b/OFDFile/src/Res.cpp @@ -0,0 +1,138 @@ +#include "Res.h" + +#include "Utils/Utils.h" + +#include "../../DesktopEditor/common/Directory.h" + +namespace OFD +{ +CRes::CRes() +{} + +CRes::~CRes() +{ + #define CLEAR_VECTOR(type, arvaribles)\ + for (const std::pair& oValue : arvaribles)\ + delete oValue.second + + CLEAR_VECTOR(CColorSpace, m_mColorSpaces); + CLEAR_VECTOR(CDrawParam, m_mDrawParams); + CLEAR_VECTOR(CFont, m_mFonts); + CLEAR_VECTOR(CMultiMedia, m_mMultiMedias); + CLEAR_VECTOR(CCompositeGraphicUnit, m_mCCompositeGraphicUnits); +} + +template +inline void AddElementToMap(T* pElement, unsigned int unIndex, std::map& mElements) +{ + if (nullptr == pElement) + return; + + typename std::map::const_iterator itFound = mElements.find(unIndex); + + if (mElements.cend() != itFound) + delete itFound->second; + + mElements.insert(std::make_pair(unIndex, pElement)); +} + +bool CRes::Read(const std::wstring& wsFilePath, const std::wstring& wsRootPath) +{ + if (wsFilePath.empty() || !CanUseThisPath(wsFilePath, wsRootPath)) + return false; + + const std::wstring wsFullPath{CombinePaths(wsRootPath, wsFilePath)}; + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(wsFullPath) || !oLiteReader.ReadNextNode() || L"ofd:Res" != oLiteReader.GetName() || oLiteReader.IsEmptyNode()) + return false; + + std::wstring wsResRootPath; + + if (0 != oLiteReader.GetAttributesCount() && oLiteReader.MoveToFirstAttribute()) + { + std::string sNodeName; + do + { + sNodeName = oLiteReader.GetNameA(); + + if ("BaseLoc" == sNodeName) + { + wsResRootPath = CombinePaths(NSDirectory::GetFolderPath(wsFullPath), oLiteReader.GetText()); + break; + } + } while (oLiteReader.MoveToNextAttribute()); + } + + oLiteReader.MoveToElement(); + + std::string sNodeName; + + #define PARSE_CONTAINER(container_name, element_name, element_type, melements, creator)\ + if (container_name == sNodeName)\ + {\ + const int nChildrenDepth = oLiteReader.GetDepth();\ + element_type* pElement = nullptr;\ + while (oLiteReader.ReadNextSiblingNode(nChildrenDepth))\ + {\ + if (element_name == oLiteReader.GetNameA())\ + {\ + pElement = creator;\ + AddElementToMap(pElement, pElement->GetID(), melements);\ + }\ + }\ + continue;\ + } + + #define PARSE_CONTAINER_WITHOUT_PATH(container_name, element_name, element_type, melements)\ + PARSE_CONTAINER(container_name, element_name, element_type, melements, new element_type(oLiteReader)) + + #define PARSE_CONTAINER_WITH_PATH(container_name, element_name, element_type, melements)\ + PARSE_CONTAINER(container_name, element_name, element_type, melements, new element_type(oLiteReader, wsResRootPath)) + + const int nDepth = oLiteReader.GetDepth(); + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + PARSE_CONTAINER_WITHOUT_PATH("ofd:ColorSpaces", "ofd:ColorSpace", CColorSpace, m_mColorSpaces) + PARSE_CONTAINER_WITHOUT_PATH("ofd:DrawParams", "ofd:DrawParam", CDrawParam, m_mDrawParams) + PARSE_CONTAINER_WITHOUT_PATH("ofd:CompositeGraphicUnits", "ofd:CCompositeGraphicUnit", CCompositeGraphicUnit, m_mCCompositeGraphicUnits) + + PARSE_CONTAINER_WITH_PATH("ofd:Fonts", "ofd:Font", CFont, m_mFonts) + PARSE_CONTAINER_WITH_PATH("ofd:MultiMedias", "ofd:MultiMedia", CMultiMedia, m_mMultiMedias) + } + + return true; +} + +#define RETURN_ELEMENT_FROM_MAP(element_type, mElements)\ + const std::map::const_iterator itFound = mElements.find(unId);\ + return (mElements.cend() != itFound) ? itFound->second : nullptr\ + +const CColorSpace* CRes::GetColorSpace(unsigned int unId) const +{ + RETURN_ELEMENT_FROM_MAP(CColorSpace, m_mColorSpaces); +} + +const CDrawParam* CRes::GetDrawParam(unsigned int unId) const +{ + RETURN_ELEMENT_FROM_MAP(CDrawParam, m_mDrawParams); +} + +const CFont* CRes::GetFont(unsigned int unId) const +{ + RETURN_ELEMENT_FROM_MAP(CFont, m_mFonts); +} + +const CMultiMedia* CRes::GetMultiMedia(unsigned int unId) const +{ + RETURN_ELEMENT_FROM_MAP(CMultiMedia, m_mMultiMedias); +} + +const CCompositeGraphicUnit* CRes::GetCompositeGraphicUnit(unsigned int unId) const +{ + RETURN_ELEMENT_FROM_MAP(CCompositeGraphicUnit, m_mCCompositeGraphicUnits); +} +} diff --git a/OFDFile/src/Res.h b/OFDFile/src/Res.h new file mode 100644 index 0000000000..c3ef7bdabd --- /dev/null +++ b/OFDFile/src/Res.h @@ -0,0 +1,37 @@ +#ifndef RES_H +#define RES_H + +#include + +#include "Types/ColorSpace.h" +#include "Types/DrawParam.h" +#include "Types/Font.h" +#include "Types/MultiMedia.h" +#include "Types/CompositeGraphicUnit.h" + +#include "../../OfficeUtils/src/ZipFolder.h" + +namespace OFD +{ +class CRes +{ + std::map m_mColorSpaces; + std::map m_mDrawParams; + std::map m_mFonts; + std::map m_mMultiMedias; + std::map m_mCCompositeGraphicUnits; +public: + CRes(); + ~CRes(); + + bool Read(const std::wstring& wsFilePath, const std::wstring& wsRootPath); + + const CColorSpace* GetColorSpace(unsigned int unId) const; + const CDrawParam* GetDrawParam(unsigned int unId) const; + const CFont* GetFont(unsigned int unId) const; + const CMultiMedia* GetMultiMedia(unsigned int unId) const; + const CCompositeGraphicUnit* GetCompositeGraphicUnit(unsigned int unId) const; +}; +} + +#endif // RES_H diff --git a/OFDFile/src/Types/Color.cpp b/OFDFile/src/Types/Color.cpp new file mode 100644 index 0000000000..4eaf1c7f9a --- /dev/null +++ b/OFDFile/src/Types/Color.cpp @@ -0,0 +1,79 @@ +#include "Color.h" + +namespace OFD +{ +CColor::CColor(CXmlReader& oXmlReader) + : m_oValues{0, 0, 0, 0}, m_nIndex(0), m_chAlpha(255), m_unColodSpaceID(0) +{ + if (0 == oXmlReader.GetAttributesCount() || !oXmlReader.MoveToFirstAttribute()) + return; + + std::string sAttributeName; + + do + { + sAttributeName = oXmlReader.GetNameA(); + + if ("ColorSpace" == sAttributeName) + m_unColodSpaceID = oXmlReader.GetUInteger(true); + else if ("Value" == sAttributeName) + { + const std::vector arValues{oXmlReader.GetArrayDoubles(true)}; + + for (unsigned int unIndex = 0; unIndex < (std::min)((unsigned int)arValues.size(), (unsigned int)4); ++unIndex) + m_oValues[unIndex] = static_cast(arValues[unIndex]); + } + else if ("Alpha" == sAttributeName) + m_chAlpha = oXmlReader.GetUInteger(true); + else if ("Index" == sAttributeName) + m_nIndex = oXmlReader.GetInteger(true); + } while (oXmlReader.MoveToNextAttribute()); + + oXmlReader.MoveToElement(); +} + +int CColor::ToInt(const CRes* pPublicRes) const +{ + if (nullptr == pPublicRes) + return 0; + + const CColorSpace* pColorSpace = pPublicRes->GetColorSpace(m_unColodSpaceID); + + CColorSpace::EType eColoSpaceType{CColorSpace::EType::RGB}; + + if (nullptr != pColorSpace) + eColoSpaceType = pColorSpace->GetType(); + + switch(eColoSpaceType) + { + case CColorSpace::EType::GRAY: + return (255 << 24) | (m_oValues[0] << 16) | (m_oValues[0] << 8) | (m_oValues[0] << 0); + case CColorSpace::EType::RGB: + return (255 << 24) | (m_oValues[2] << 16) | (m_oValues[1] << 8) | (m_oValues[0] << 0); + case CColorSpace::EType::CMYK: + { + const float cF = m_oValues[0] / 255.0f; + const float mF = m_oValues[1] / 255.0f; + const float yF = m_oValues[2] / 255.0f; + const float kF = m_oValues[3] / 255.0f; + + const float r = (1.0f - cF) * (1.0f - kF); + const float g = (1.0f - mF) * (1.0f - kF); + const float b = (1.0f - yF) * (1.0f - kF); + + const unsigned char rByte = static_cast(r * 255); + const unsigned char gByte = static_cast(g * 255); + const unsigned char bByte = static_cast(b * 255); + + return (rByte << 0) | (gByte << 8) | (bByte << 16); + } + } + + return 0; +} + +BYTE CColor::GetAlpha() const +{ + return m_chAlpha; +} +} diff --git a/OFDFile/src/Types/Color.h b/OFDFile/src/Types/Color.h new file mode 100644 index 0000000000..23688225e7 --- /dev/null +++ b/OFDFile/src/Types/Color.h @@ -0,0 +1,30 @@ +#ifndef COLOR_H +#define COLOR_H + +#include "../Utils/XmlReader.h" +#include "../Res.h" + +namespace OFD +{ +class CColor +{ + BYTE m_oValues[4]; + + int m_nIndex; + BYTE m_chAlpha; + + unsigned int m_unColodSpaceID; + // Pattern + // AxialShd + // RadialShd + // GouraudShd + // LaGouraudhd +public: + CColor(CXmlReader& oXmlReader); + + int ToInt(const CRes* pPublicRes) const; + BYTE GetAlpha() const; +}; +} + +#endif // COLOR_H diff --git a/OFDFile/src/Types/ColorSpace.cpp b/OFDFile/src/Types/ColorSpace.cpp new file mode 100644 index 0000000000..3dfd6e5e45 --- /dev/null +++ b/OFDFile/src/Types/ColorSpace.cpp @@ -0,0 +1,35 @@ +#include "ColorSpace.h" + +namespace OFD +{ +CColorSpace::CColorSpace(CXmlReader& oXmlReader) + : IOFDElement(oXmlReader) +{ + if (0 != oXmlReader.GetAttributesCount() && oXmlReader.MoveToFirstAttribute()) + { + std::string sArgumentName; + do + { + sArgumentName = oXmlReader.GetNameA(); + + if ("Type" == sArgumentName) + { + const std::string sValue{oXmlReader.GetTextA()}; + + if ("Gray" == sValue) + m_eType = EType::GRAY; + else if ("RGB" == sValue) + m_eType = EType::RGB; + else if ("CMYK" == sValue) + m_eType = EType::CMYK; + } + } while (oXmlReader.MoveToNextAttribute()); + } + oXmlReader.MoveToElement(); +} + +CColorSpace::EType CColorSpace::GetType() const +{ + return m_eType; +} +} diff --git a/OFDFile/src/Types/ColorSpace.h b/OFDFile/src/Types/ColorSpace.h new file mode 100644 index 0000000000..19dceaf87d --- /dev/null +++ b/OFDFile/src/Types/ColorSpace.h @@ -0,0 +1,25 @@ +#ifndef COLORSPACE_H +#define COLORSPACE_H + +#include "../IOFDElement.h" + +namespace OFD +{ +class CColorSpace : public IOFDElement +{ +public: + CColorSpace(CXmlReader& oXmlReader); + + enum class EType + { + GRAY, + RGB, + CMYK + }; + + EType GetType() const; +private: + EType m_eType; +}; +} +#endif // COLORSPACE_H diff --git a/OFDFile/src/Types/CommonData.cpp b/OFDFile/src/Types/CommonData.cpp new file mode 100644 index 0000000000..e781b6fbb1 --- /dev/null +++ b/OFDFile/src/Types/CommonData.cpp @@ -0,0 +1,88 @@ +#include "CommonData.h" +#include "../Utils/Utils.h" + +namespace OFD +{ +CCommonData::CCommonData() + : m_unMaxUnitID(0), m_pPublicRes(nullptr), m_pDocumentRes(nullptr) +{} + +CCommonData::~CCommonData() +{ + if (nullptr != m_pPublicRes) + delete m_pPublicRes; + + if (nullptr != m_pDocumentRes) + delete m_pDocumentRes; +} + +bool CCommonData::Read(CXmlReader& oLiteReader, const std::wstring& wsRootPath) +{ + if ("ofd:CommonData" != oLiteReader.GetNameA()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + std::string sNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + if ("ofd:PageArea" == sNodeName) + m_oPageArea.Read(oLiteReader); + else if ("ofd:PublicRes" == sNodeName) + { + if (nullptr == m_pPublicRes) + m_pPublicRes = new CRes(); + + m_pPublicRes->Read(oLiteReader.GetText2(), wsRootPath); + } + else if ("ofd:DocumentRes" == sNodeName) + { + if(nullptr == m_pDocumentRes) + m_pDocumentRes = new CRes(); + + m_pDocumentRes->Read(oLiteReader.GetText2(), wsRootPath); + } + else if ("ofd:MaxUnitID" == sNodeName) + m_unMaxUnitID = oLiteReader.GetUInteger(); + else if ("ofd:TemplatePage" == sNodeName) + AddToContainer(new const CTemplatePage(oLiteReader, wsRootPath), m_arTemplatePages); + // else if (L"ofd:DefaultCS" == wsNodeName) + } + + return true; +} + +void CCommonData::GetPageSize(double& dWidth, double& dHeight) const +{ + TBox oPhysicalBox{m_oPageArea.GetPhysicalBox()}; + + if (oPhysicalBox.Empty()) + return; + + dWidth = oPhysicalBox.m_dWidth; + dHeight = oPhysicalBox.m_dHeight; +} + +const CRes* CCommonData::GetPublicRes() const +{ + return m_pPublicRes; +} + +const CRes* CCommonData::GetDocumentRes() const +{ + return m_pDocumentRes; +} + +const CTemplatePage* CCommonData::GetTemplatePage(unsigned int unTemplateID, EZOrder eZOrder) const +{ + for (const CTemplatePage* pTemplatePage : m_arTemplatePages) + { + if (unTemplateID == pTemplatePage->GetID() && eZOrder == pTemplatePage->GetZOrder()) + return pTemplatePage; + } + + return nullptr; +} +} diff --git a/OFDFile/src/Types/CommonData.h b/OFDFile/src/Types/CommonData.h new file mode 100644 index 0000000000..c7b88f4320 --- /dev/null +++ b/OFDFile/src/Types/CommonData.h @@ -0,0 +1,33 @@ +#ifndef COMMONDATA_H +#define COMMONDATA_H + +#include "../Res.h" +#include "PageArea.h" +#include "TemplatePage.h" + +namespace OFD +{ +class CCommonData +{ + unsigned int m_unMaxUnitID; + CPageArea m_oPageArea; + CRes* m_pPublicRes; + CRes* m_pDocumentRes; + + std::vector m_arTemplatePages; +public: + CCommonData(); + ~CCommonData(); + + bool Read(CXmlReader& oLiteReader, const std::wstring& wsRootPath); + + void GetPageSize(double& dWidth, double &dHeight) const; + + const CRes* GetPublicRes() const; + const CRes* GetDocumentRes() const; + + const CTemplatePage* GetTemplatePage(unsigned int unTemplateID, EZOrder eZOrder) const; +}; +} + +#endif // COMMONDATA_H diff --git a/OFDFile/src/Types/CompositeGraphicUnit.cpp b/OFDFile/src/Types/CompositeGraphicUnit.cpp new file mode 100644 index 0000000000..5ecaa06d88 --- /dev/null +++ b/OFDFile/src/Types/CompositeGraphicUnit.cpp @@ -0,0 +1,8 @@ +#include "CompositeGraphicUnit.h" + +namespace OFD +{ +CCompositeGraphicUnit::CCompositeGraphicUnit(CXmlReader& oXmlReader) + : IOFDElement(oXmlReader) +{} +} diff --git a/OFDFile/src/Types/CompositeGraphicUnit.h b/OFDFile/src/Types/CompositeGraphicUnit.h new file mode 100644 index 0000000000..be593f293b --- /dev/null +++ b/OFDFile/src/Types/CompositeGraphicUnit.h @@ -0,0 +1,15 @@ +#ifndef COMPOSITEGRAPHICUNIT_H +#define COMPOSITEGRAPHICUNIT_H + +#include "../IOFDElement.h" + +namespace OFD +{ +class CCompositeGraphicUnit : public IOFDElement +{ +public: + CCompositeGraphicUnit(CXmlReader& oXmlReader); +}; +} + +#endif // COMPOSITEGRAPHICUNIT_H diff --git a/OFDFile/src/Types/DrawParam.cpp b/OFDFile/src/Types/DrawParam.cpp new file mode 100644 index 0000000000..c1738b429c --- /dev/null +++ b/OFDFile/src/Types/DrawParam.cpp @@ -0,0 +1,8 @@ +#include "DrawParam.h" + +namespace OFD +{ +CDrawParam::CDrawParam(CXmlReader& oXmlReader) + : IOFDElement(oXmlReader) +{} +} diff --git a/OFDFile/src/Types/DrawParam.h b/OFDFile/src/Types/DrawParam.h new file mode 100644 index 0000000000..90d8080ca1 --- /dev/null +++ b/OFDFile/src/Types/DrawParam.h @@ -0,0 +1,14 @@ +#ifndef DRAWPARAM_H +#define DRAWPARAM_H + +#include "../IOFDElement.h" + +namespace OFD +{ +class CDrawParam : public IOFDElement +{ +public: + CDrawParam(CXmlReader& oXmlReader); +}; +} +#endif // DRAWPARAM_H diff --git a/OFDFile/src/Types/Font.cpp b/OFDFile/src/Types/Font.cpp new file mode 100644 index 0000000000..a596884160 --- /dev/null +++ b/OFDFile/src/Types/Font.cpp @@ -0,0 +1,76 @@ +#include "Font.h" + +#include "../Utils/Utils.h" + +namespace OFD +{ +CFont::CFont(CXmlReader& oXmlReader, const std::wstring& wsRootPath) + : IOFDElement(oXmlReader), + m_wsCharset(L"unicode"), m_bItalic(false), m_bBold(false), + m_bSerif(false), m_bFixedWidth(false) +{ + if (0 != oXmlReader.GetAttributesCount() && oXmlReader.MoveToFirstAttribute()) + { + std::string sArgumentName; + + do + { + sArgumentName = oXmlReader.GetNameA(); + + if ("FontName" == sArgumentName) + m_wsFontName = oXmlReader.GetText(); + else if ("FamilyName" == sArgumentName) + m_wsFamilyName = oXmlReader.GetText(); + else if ("Charset" == sArgumentName) + m_wsCharset = oXmlReader.GetText(); + else if ("Italic" == sArgumentName) + m_bItalic = oXmlReader.GetBoolean(true); + else if ("Bold" == sArgumentName) + m_bBold = oXmlReader.GetBoolean(true); + else if ("Serif" == sArgumentName) + m_bSerif = oXmlReader.GetBoolean(true); + else if ("FixedWidth" == sArgumentName) + m_bFixedWidth = oXmlReader.GetBoolean(true); + } while (oXmlReader.MoveToNextAttribute()); + } + + oXmlReader.MoveToElement(); + + if (oXmlReader.IsEmptyNode()) + return; + + const int nDepth = oXmlReader.GetDepth(); + + while (oXmlReader.ReadNextSiblingNode(nDepth)) + { + if ("ofd:FontFile" == oXmlReader.GetNameA()) + { + const std::wstring wsPath{oXmlReader.GetText2()}; + + if (CanUseThisPath(wsPath, wsRootPath)) + m_wsFilePath = CombinePaths(wsRootPath, wsPath); + + break; + } + } +} + +void CFont::Apply(IRenderer* pRenderer) const +{ + if (nullptr == pRenderer) + return; + + int nFontStyle = 0; + + if (m_bBold) + nFontStyle |= 0x01; + if (m_bItalic) + nFontStyle |= 0x02; + + pRenderer->put_FontStyle(nFontStyle); + pRenderer->put_FontName(m_wsFontName); + + if (!m_wsFilePath.empty()) + pRenderer->put_FontPath(m_wsFilePath); +} +} diff --git a/OFDFile/src/Types/Font.h b/OFDFile/src/Types/Font.h new file mode 100644 index 0000000000..dc3c698ff8 --- /dev/null +++ b/OFDFile/src/Types/Font.h @@ -0,0 +1,29 @@ +#ifndef FONT_H +#define FONT_H + +#include "../IOFDElement.h" + +#include "../../../DesktopEditor/graphics/IRenderer.h" + +namespace OFD +{ +class CFont : public IOFDElement +{ +public: + CFont(CXmlReader& oXmlReader, const std::wstring& wsRootPath); + + void Apply(IRenderer* pRenderer) const; +private: + std::wstring m_wsFontName; + std::wstring m_wsFamilyName; + std::wstring m_wsCharset; + bool m_bItalic; + bool m_bBold; + bool m_bSerif; + bool m_bFixedWidth; + + std::wstring m_wsFilePath; +}; +} + +#endif // FONT_H diff --git a/OFDFile/src/Types/MultiMedia.cpp b/OFDFile/src/Types/MultiMedia.cpp new file mode 100644 index 0000000000..a3cd0ffb04 --- /dev/null +++ b/OFDFile/src/Types/MultiMedia.cpp @@ -0,0 +1,61 @@ +#include "MultiMedia.h" + +#include "../Utils/Utils.h" + +namespace OFD +{ +CMultiMedia::CMultiMedia(CXmlReader& oXmlReader, const std::wstring& wsRootPath) + : IOFDElement(oXmlReader), m_eType(EType::Image) +{ + if (0 != oXmlReader.GetAttributesCount() && oXmlReader.MoveToFirstAttribute()) + { + std::string sArgumentName; + do + { + sArgumentName = oXmlReader.GetNameA(); + + if ("Type" == sArgumentName) + { + const std::string sValue{oXmlReader.GetTextA()}; + + if ("Image" == sValue) + m_eType = EType::Image; + else if ("Audio" == sValue) + m_eType = EType::Audio; + else if ("Video" == sValue) + m_eType = EType::Video; + } + } while (oXmlReader.MoveToNextAttribute()); + } + + oXmlReader.MoveToElement(); + + if (oXmlReader.IsEmptyNode()) + return; + + const int nDepth = oXmlReader.GetDepth(); + + while (oXmlReader.ReadNextSiblingNode(nDepth)) + { + if ("ofd:MediaFile" == oXmlReader.GetNameA()) + { + const std::wstring wsPath{oXmlReader.GetText2()}; + + if (CanUseThisPath(wsPath, wsRootPath)) + m_wsFilePath = CombinePaths(wsRootPath, wsPath); + + break; + } + } +} + +CMultiMedia::EType CMultiMedia::GetType() const +{ + return m_eType; +} + +std::wstring CMultiMedia::GetFilePath() const +{ + return m_wsFilePath; +} +} diff --git a/OFDFile/src/Types/MultiMedia.h b/OFDFile/src/Types/MultiMedia.h new file mode 100644 index 0000000000..2435a91cd4 --- /dev/null +++ b/OFDFile/src/Types/MultiMedia.h @@ -0,0 +1,28 @@ +#ifndef MULTIMEDIA_H +#define MULTIMEDIA_H + +#include "../IOFDElement.h" + +namespace OFD +{ +class CMultiMedia : public IOFDElement +{ +public: + CMultiMedia(CXmlReader& oXmlReader, const std::wstring& wsRootPath); + + enum class EType + { + Image, + Audio, + Video + }; + + EType GetType() const; + std::wstring GetFilePath() const; +private: + EType m_eType; + std::wstring m_wsFilePath; +}; +} + +#endif // MULTIMEDIA_H diff --git a/OFDFile/src/Types/PageArea.cpp b/OFDFile/src/Types/PageArea.cpp new file mode 100644 index 0000000000..77130b614b --- /dev/null +++ b/OFDFile/src/Types/PageArea.cpp @@ -0,0 +1,39 @@ +#include "PageArea.h" + +namespace OFD +{ +CPageArea::CPageArea() +{} + +bool CPageArea::Read(CXmlReader& oLiteReader) +{ + if (!oLiteReader.IsEmptyNode() && + L"ofd:PageArea" != oLiteReader.GetName() && + L"ofd:Area" != oLiteReader.GetName()) + return false; + + const int nDepth = oLiteReader.GetDepth(); + std::wstring wsNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + wsNodeName = oLiteReader.GetName(); + + if (L"ofd:PhysicalBox" == wsNodeName) + m_oPhysicalBox.Read(oLiteReader.GetText2A()); + else if (L"ofd:ApplicationBox" == wsNodeName) + m_oApplicationBox.Read(oLiteReader.GetText2A()); + else if (L"ofd:ContentBox" == wsNodeName) + m_oContentBox.Read(oLiteReader.GetText2A()); + else if (L"ofd:BleedBox" == wsNodeName) + m_oBleedBox.Read(oLiteReader.GetText2A()); + } + + return true; +} + +TBox CPageArea::GetPhysicalBox() const +{ + return m_oPhysicalBox; +} +} diff --git a/OFDFile/src/Types/PageArea.h b/OFDFile/src/Types/PageArea.h new file mode 100644 index 0000000000..a0ec64a23e --- /dev/null +++ b/OFDFile/src/Types/PageArea.h @@ -0,0 +1,23 @@ +#ifndef PAGEAREA_H +#define PAGEAREA_H + +#include "../Utils/XmlReader.h" +#include "../Utils/Types.h" + +namespace OFD +{ +class CPageArea +{ + TBox m_oPhysicalBox; + TBox m_oApplicationBox; + TBox m_oContentBox; + TBox m_oBleedBox; +public: + CPageArea(); + + bool Read(CXmlReader& oLiteReader); + + TBox GetPhysicalBox() const; +}; +} +#endif // PAGEAREA_H diff --git a/OFDFile/src/Types/Signature.cpp b/OFDFile/src/Types/Signature.cpp new file mode 100644 index 0000000000..bc82a71427 --- /dev/null +++ b/OFDFile/src/Types/Signature.cpp @@ -0,0 +1,186 @@ +#include "Signature.h" + +#include "../Utils/Utils.h" + +#include "../OFDFile_Private.h" + +namespace OFD +{ +CSignature::CSignature() +{} + +CSignature* CSignature::Read(const std::wstring& wsFilePath, IFolder* pFolder) +{ + if (wsFilePath.empty() || !CanUseThisPath(wsFilePath, pFolder->getFullFilePath(L""))) + return nullptr; + + CXmlReader oLiteReader; + if (!oLiteReader.FromFile(CombinePaths(pFolder->getFullFilePath(L""), wsFilePath)) || !oLiteReader.ReadNextNode() || L"ofd:Signature" != oLiteReader.GetName() || oLiteReader.IsEmptyNode()) + return nullptr; + + CSignature *pSignature = new CSignature(); + + pSignature->m_wsRootPath = pFolder->getFullFilePath(L""); + + const int nDepth = oLiteReader.GetDepth(); + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + if ("ofd:SignedInfo" == oLiteReader.GetNameA()) + pSignature->m_oSignedInfo.Read(oLiteReader); + else if ("ofd:SignedValue" == oLiteReader.GetNameA()) + pSignature->m_wsSignedValue = CombinePaths(pSignature->m_wsRootPath, oLiteReader.GetText2()); + } + + return pSignature; +} + +bool CSignature::Draw(IRenderer* pRenderer, unsigned int unPageIndex, NSFonts::IApplicationFonts* pFonts) const +{ + if (nullptr == pRenderer || m_wsSignedValue.empty() || + m_oSignedInfo.m_oStampAnnot.m_unPageRef - 1 != unPageIndex || + m_oSignedInfo.m_oStampAnnot.m_oBoundary.Empty()) + return false; + + COFDFile_Private oFile(pFonts); + oFile.SetTempDir(m_wsRootPath); + + oFile.LoadFromFile(m_wsSignedValue); + + oFile.DrawPage(pRenderer, 0, + m_oSignedInfo.m_oStampAnnot.m_oBoundary.m_dX, + m_oSignedInfo.m_oStampAnnot.m_oBoundary.m_dY, + m_oSignedInfo.m_oStampAnnot.m_oBoundary.m_dWidth, + m_oSignedInfo.m_oStampAnnot.m_oBoundary.m_dHeight); + + return false; +} + +void TProvider::Read(CXmlReader& oLiteReader) +{ + if (0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return; + + std::string sAttributeName; + + do + { + sAttributeName = oLiteReader.GetNameA(); + + if ("ProviderName" == sAttributeName) + m_wsProviderName = oLiteReader.GetText(); + else if ("Version" == sAttributeName) + m_wsVersion = oLiteReader.GetText(); + else if ("Company" == sAttributeName) + m_wsCompany = oLiteReader.GetText(); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); +} + +TReference* TReference::Read(CXmlReader& oLiteReader) +{ + if ("ofd:Reference" != oLiteReader.GetNameA() || oLiteReader.IsEmptyElement() || 0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return nullptr; + + TReference* pElement = new TReference(); + + do + { + if ("FileRef" == oLiteReader.GetNameA()) + pElement->m_wsFileRef = oLiteReader.GetText(); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); + + const int nDepth = oLiteReader.GetDepth(); + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + if ("ofd:CheckValue" == oLiteReader.GetNameA()) + { + pElement->m_wsCheckValue = oLiteReader.GetText2(); + break; + } + } + + return pElement; +} + +TReferences::~TReferences() +{ + ClearContainer(m_arValues); +} + +void TReferences::Read(CXmlReader& oLiteReader) +{ + if (oLiteReader.IsEmptyElement() || 0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return; + + do + { + if ("CheckMethod" == oLiteReader.GetNameA()) + m_wsCheckMethod = oLiteReader.GetText(); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); + + const int nDepth = oLiteReader.GetDepth(); + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + AddToContainer(TReference::Read(oLiteReader), m_arValues); +} + +TStampAnnot::TStampAnnot() + : m_unID(0), m_unPageRef(0) +{} + +void TStampAnnot::Read(CXmlReader& oLiteReader) +{ + if (0 == oLiteReader.GetAttributesCount() || !oLiteReader.MoveToFirstAttribute()) + return; + + std::string sAttributeName; + + do + { + sAttributeName = oLiteReader.GetNameA(); + + if ("ID" == sAttributeName) + m_unID = oLiteReader.GetUInteger(true); + else if ("PageRef" == sAttributeName) + m_unPageRef = oLiteReader.GetUInteger(true); + else if ("Boundary" == sAttributeName) + m_oBoundary.Read(oLiteReader.GetTextA()); + } while (oLiteReader.MoveToNextAttribute()); + + oLiteReader.MoveToElement(); +} + +void TSignedInfo::Read(CXmlReader& oLiteReader) +{ + if (oLiteReader.IsEmptyNode()) + return; + + const int nDepth = oLiteReader.GetDepth(); + + std::string sNodeName; + + while (oLiteReader.ReadNextSiblingNode(nDepth)) + { + sNodeName = oLiteReader.GetNameA(); + + if ("ofd:Provider" == sNodeName) + m_oProvider.Read(oLiteReader); + else if ("ofd:SignatureMethod" == sNodeName) + m_wsSignatureMethod = oLiteReader.GetText2(); + else if ("ofd:SignatureDateTime" == sNodeName) + m_wsSignatureDateTime = oLiteReader.GetText2(); + else if ("ofd:References" == sNodeName) + m_oReferences.Read(oLiteReader); + else if ("ofd:StampAnnot" == sNodeName) + m_oStampAnnot.Read(oLiteReader); + } +} + +} diff --git a/OFDFile/src/Types/Signature.h b/OFDFile/src/Types/Signature.h new file mode 100644 index 0000000000..d2184637c1 --- /dev/null +++ b/OFDFile/src/Types/Signature.h @@ -0,0 +1,78 @@ +#ifndef SIGNATURE_H +#define SIGNATURE_H + +#include "../../../DesktopEditor/graphics/pro/Fonts.h" +#include "../../../DesktopEditor/graphics/IRenderer.h" + +#include "../../../OfficeUtils/src/ZipFolder.h" + +#include "../Utils/XmlReader.h" +#include "../Utils/Types.h" + +namespace OFD +{ +struct TProvider +{ + std::wstring m_wsProviderName; + std::wstring m_wsVersion; + std::wstring m_wsCompany; + + void Read(CXmlReader& oLiteReader); +}; + +struct TReference +{ + std::wstring m_wsFileRef; + std::wstring m_wsCheckValue; + + static TReference* Read(CXmlReader& oLiteReader); +}; + +struct TReferences +{ + std::wstring m_wsCheckMethod; + std::vector m_arValues; + + ~TReferences(); + + void Read(CXmlReader& oLiteReader); +}; + +struct TStampAnnot +{ + unsigned int m_unID; + unsigned int m_unPageRef; + TBox m_oBoundary; + + TStampAnnot(); + + void Read(CXmlReader& oLiteReader); +}; + +struct TSignedInfo +{ + TProvider m_oProvider; + std::wstring m_wsSignatureMethod; + std::wstring m_wsSignatureDateTime; + TReferences m_oReferences; + TStampAnnot m_oStampAnnot; + + void Read(CXmlReader& oLiteReader); +}; + +class CSignature +{ + TSignedInfo m_oSignedInfo; + std::wstring m_wsSignedValue; + + std::wstring m_wsRootPath; +public: + CSignature(); + + static CSignature* Read(const std::wstring& wsFilePath, IFolder* pFolder); + + bool Draw(IRenderer* pRenderer, unsigned int unPageIndex, NSFonts::IApplicationFonts* pFonts) const; +}; +} + +#endif // SIGNATURE_H diff --git a/OFDFile/src/Types/TemplatePage.cpp b/OFDFile/src/Types/TemplatePage.cpp new file mode 100644 index 0000000000..4821a10d5f --- /dev/null +++ b/OFDFile/src/Types/TemplatePage.cpp @@ -0,0 +1,53 @@ +#include "TemplatePage.h" + +#include "../Page.h" + +namespace OFD +{ +CTemplatePage::CTemplatePage(CXmlReader& oXmlReader, const std::wstring& wsRootPath) + : IOFDElement(oXmlReader), m_eZOrder(EZOrder::Background), m_pPage(nullptr) +{ + if ("ofd:TemplatePage" != oXmlReader.GetNameA() || 0 == oXmlReader.GetAttributesCount() || !oXmlReader.MoveToFirstAttribute()) + return; + + std::string sAttributeName; + do + { + sAttributeName = oXmlReader.GetNameA(); + + if ("BaseLoc" == sAttributeName) + m_pPage = CPage::Read(oXmlReader.GetText(), wsRootPath); + else if ("ZOrder" == sAttributeName) + m_eZOrder = GetZOrderFromString(oXmlReader.GetTextA()); + } while (oXmlReader.MoveToNextAttribute()); + + oXmlReader.MoveToElement(); +} + +CTemplatePage::~CTemplatePage() +{ + if (nullptr != m_pPage) + delete m_pPage; +} + +EZOrder CTemplatePage::GetZOrder() const +{ + return m_eZOrder; +} + +const CPage* CTemplatePage::GetPage() const +{ + return m_pPage; +} + +EZOrder GetZOrderFromString(const std::string& sValue) +{ + if ("Body" == sValue) + return EZOrder::Body; + if ("Background" == sValue) + return EZOrder::Background; + + return EZOrder::Body; +} + +} diff --git a/OFDFile/src/Types/TemplatePage.h b/OFDFile/src/Types/TemplatePage.h new file mode 100644 index 0000000000..6b3d679614 --- /dev/null +++ b/OFDFile/src/Types/TemplatePage.h @@ -0,0 +1,31 @@ +#ifndef TEMPLATEPAGE_H +#define TEMPLATEPAGE_H + +#include "../IOFDElement.h" + +namespace OFD +{ +enum class EZOrder +{ + Body, + Background +} ; + +EZOrder GetZOrderFromString(const std::string& sValue); + +class CPage; +class CTemplatePage : public IOFDElement +{ + EZOrder m_eZOrder; + + const CPage* m_pPage; +public: + CTemplatePage(CXmlReader& oXmlReader, const std::wstring& wsRootPath); + ~CTemplatePage(); + + EZOrder GetZOrder() const; + const CPage* GetPage() const; +}; +} + +#endif // TEMPLATEPAGE_H diff --git a/OFDFile/src/Utils/Types.cpp b/OFDFile/src/Utils/Types.cpp new file mode 100644 index 0000000000..5d1f20c6b4 --- /dev/null +++ b/OFDFile/src/Utils/Types.cpp @@ -0,0 +1,54 @@ +#include "Types.h" + +#include "Utils.h" + +namespace OFD +{ +TBox::TBox() + : m_dX(0.), m_dY(0.), m_dWidth(0.), m_dHeight(0.) +{} + +bool TBox::Empty() const +{ + return m_dWidth < OFD_EPSILON || m_dHeight < OFD_EPSILON; +} + +bool TBox::Read(const std::string& sValue) +{ + const std::vector arValues{Split(sValue, ' ')}; + + if (4 > arValues.size()) + return false; + + if (!StringToDouble(arValues[0], m_dX) || + !StringToDouble(arValues[1], m_dY) || + !StringToDouble(arValues[2], m_dWidth) || + !StringToDouble(arValues[3], m_dHeight)) + return false; + + return true; +} + +TMatrix::TMatrix() + : m_dM11(1.), m_dM12(0.), m_dM21(0.), m_dM22(1.), m_dDx(0.), m_dDy(0.) +{} + +bool TMatrix::Read(const std::string& sValue) +{ + const std::vector arValues{Split(sValue, ' ')}; + + if (6 > arValues.size()) + return false; + + if (!StringToDouble(arValues[0], m_dM11) || + !StringToDouble(arValues[1], m_dM12) || + !StringToDouble(arValues[2], m_dM21) || + !StringToDouble(arValues[3], m_dM22) || + !StringToDouble(arValues[4], m_dDx) || + !StringToDouble(arValues[5], m_dDy)) + return false; + + return true; +} + +} diff --git a/OFDFile/src/Utils/Types.h b/OFDFile/src/Utils/Types.h new file mode 100644 index 0000000000..c245f3476c --- /dev/null +++ b/OFDFile/src/Utils/Types.h @@ -0,0 +1,37 @@ +#ifndef TYPES_H +#define TYPES_H + +#include + +namespace OFD +{ +#define OFD_EPSILON 0.0001 +struct TBox +{ + double m_dX; + double m_dY; + double m_dWidth; + double m_dHeight; + + TBox(); + + bool Empty() const; + bool Read(const std::string& wsValue); +}; + +struct TMatrix +{ + double m_dM11; + double m_dM12; + double m_dM21; + double m_dM22; + double m_dDx; + double m_dDy; + + TMatrix(); + + bool Read(const std::string& sValue); +}; +} + +#endif // TYPES_H diff --git a/OFDFile/src/Utils/Utils.h b/OFDFile/src/Utils/Utils.h new file mode 100644 index 0000000000..096f878d9b --- /dev/null +++ b/OFDFile/src/Utils/Utils.h @@ -0,0 +1,174 @@ +#ifndef UTILS_H +#define UTILS_H + +#include +#include +#include +#include +#include +#include + +#include "../../../DesktopEditor/common/Path.h" +#include "../../../DesktopEditor/common/ProcessEnv.h" + +#include + +namespace OFD +{ +inline std::vector Split(const std::string& sValue, char chDelim) +{ + if (sValue.empty()) + return std::vector(); + + std::vector arValues; + std::stringstream oStringStream(sValue); + std::string sItem; + + while (std::getline(oStringStream, sItem, chDelim)) + arValues.push_back(sItem); + + return arValues; +} + +inline bool StringToBoolean(const std::string& sValue, bool& bValue) +{ + //TODO:: скорректировать метод, если возможно чтение не стандартных значений с плавающей запятой + if (sValue.empty()) + return false; + + size_t unStart = sValue.find_first_not_of(" \t\n\r\f\v"); + + if (std::string::npos == unStart) + return false; + + size_t unEnd = sValue.find_last_not_of(" \t\n\r\f\v"); + + std::string sTrimmed = sValue.substr(unStart, unEnd - unStart + 1); + + std::transform(sTrimmed.begin(), sTrimmed.end(), sTrimmed.begin(), + [](unsigned char c){ return std::tolower(c); }); + + bValue = "true" == sTrimmed; + return true; +} + +inline bool StringToInteger(const std::string& sValue, int& nValue) +{ + //TODO:: скорректировать метод, если возможно чтение не стандартных значений с плавающей запятой + if (sValue.empty()) + return false; + + char* pEnd = nullptr; + + nValue = std::strtol(sValue.c_str(), &pEnd, 10); + + if (pEnd == sValue.c_str() || '\0' != *pEnd) + return false; + + return true; +} + +inline bool StringToUInteger(const std::string& sValue, unsigned int& unValue) +{ + //TODO:: скорректировать метод, если возможно чтение не стандартных значений с плавающей запятой + if (sValue.empty()) + return false; + + char* pEnd = nullptr; + + unValue = std::strtoul(sValue.c_str(), &pEnd, 10); + + if (pEnd == sValue.c_str() || '\0' != *pEnd) + return false; + + return true; +} + +inline bool StringToDouble(const std::string& sValue, double& dValue) +{ + //TODO:: скорректировать метод, если возможно чтение не стандартных значений с плавающей запятой + if (sValue.empty()) + return false; + + char* pEnd = nullptr; + + dValue = std::strtod(sValue.c_str(), &pEnd); + + if (pEnd == sValue.c_str() || '\0' != *pEnd) + return false; + + return true; +} + +template +inline void AddToContainer(T* pValue, std::vector& arValues) +{ + if (nullptr != pValue) + arValues.push_back(pValue); +} + +template +inline void ClearContainer(std::vector& arValues) +{ + for (T* pElement : arValues) + if (nullptr != pElement) + delete pElement; + + arValues.clear(); +} + +inline std::wstring CombinePaths(const std::wstring& wsFirstPath, const std::wstring& wsSecondPath) +{ + if (wsFirstPath.empty()) + return wsSecondPath; + + if (wsSecondPath.empty()) + return wsFirstPath; + + std::wstring::const_reverse_iterator itFound = std::find_if(wsFirstPath.crbegin(), wsFirstPath.crend(), [](wchar_t wChar){ return L'/' == wChar || L'\\' == wChar; }); + + if (wsFirstPath.crend() == itFound) + return NSSystemPath::Combine(wsFirstPath, wsSecondPath); + + std::wstring wsNewSecondPath{wsSecondPath}; + + if (L'/' == wsNewSecondPath[0] || L'\\' == wsNewSecondPath[0]) + wsNewSecondPath.erase(0, 1); + + const std::wstring& wsFirstDirName = wsFirstPath.substr(itFound.base() - wsFirstPath.cbegin(), wsFirstPath.cend() - itFound.base()); + + if (wsFirstDirName == wsNewSecondPath.substr(0, wsFirstDirName.length())) + wsNewSecondPath.erase(0, wsFirstDirName.length()); + + return NSSystemPath::Combine(wsFirstPath, wsNewSecondPath); +} + +inline bool GetStatusUsingExternalLocalFiles() +{ + return false; + + if (NSProcessEnv::IsPresent(NSProcessEnv::Converter::gc_allowPrivateIP)) + return NSProcessEnv::GetBoolValue(NSProcessEnv::Converter::gc_allowPrivateIP); + + return true; +} + +inline bool CanUseThisPath(const std::wstring& wsPath, const std::wstring& wsRootPath) +{ + if (GetStatusUsingExternalLocalFiles()) + return true; + + const std::wstring wsFullPath = NSSystemPath::ShortenPath(NSSystemPath::Combine(wsRootPath, wsPath)); + + if (!wsRootPath.empty()) + return boost::starts_with(wsFullPath, wsRootPath); + + return !boost::starts_with(wsFullPath, L"../"); +} + +inline bool IsZeroValue(const double& dValue) +{ + return DBL_EPSILON > std::abs(dValue); +} +} +#endif // UTILS_H diff --git a/OFDFile/src/Utils/XmlReader.cpp b/OFDFile/src/Utils/XmlReader.cpp new file mode 100644 index 0000000000..99ff9f924c --- /dev/null +++ b/OFDFile/src/Utils/XmlReader.cpp @@ -0,0 +1,68 @@ +#include "XmlReader.h" + +#include "Utils.h" + +namespace OFD +{ +CXmlReader::CXmlReader() +{} + +std::wstring CXmlReader::GetTextValue(bool bIsAttribute) +{ + return (bIsAttribute) ? XmlUtils::CXmlLiteReader::GetText() : XmlUtils::CXmlLiteReader::GetText2(); +} + +std::string CXmlReader::GetTextValueA(bool bIsAttribute) +{ + return (bIsAttribute) ? XmlUtils::CXmlLiteReader::GetTextA() : XmlUtils::CXmlLiteReader::GetText2A(); +} + +bool CXmlReader::GetBoolean(bool bIsAttribute) +{ + bool bValue = false; + StringToBoolean(GetTextValueA(bIsAttribute), bValue); + return bValue; +} + +int CXmlReader::GetInteger(bool bIsAttribute) +{ + int nValue = 0; + StringToInteger(GetTextValueA(bIsAttribute), nValue); + return nValue; +} + +unsigned int CXmlReader::GetUInteger(bool bIsAttribute) +{ + unsigned int unValue = 0; + StringToUInteger(GetTextValueA(bIsAttribute), unValue); + return unValue; +} + +double CXmlReader::GetDouble(bool bIsAttribute) +{ + double dValue = 0.; + StringToDouble(GetTextValueA(bIsAttribute), dValue); + return dValue; +} + +std::vector CXmlReader::GetArrayStrings(bool bIsAttribute) +{ + return Split(GetTextValueA(bIsAttribute), ' '); +} + +std::vector CXmlReader::GetArrayDoubles(bool bIsAttribute) +{ + const std::vector arValues{Split(GetTextValueA(bIsAttribute), ' ')}; + + if(arValues.empty()) + return std::vector(); + + std::vector arDoubleValues(arValues.size()); + + for (unsigned int unIndex = 0; unIndex < arValues.size(); ++unIndex) + if (!StringToDouble(arValues[unIndex], arDoubleValues[unIndex])) + return std::vector(); + + return arDoubleValues; +} +} diff --git a/OFDFile/src/Utils/XmlReader.h b/OFDFile/src/Utils/XmlReader.h new file mode 100644 index 0000000000..6d1e46773a --- /dev/null +++ b/OFDFile/src/Utils/XmlReader.h @@ -0,0 +1,26 @@ +#ifndef XMLREADER_H +#define XMLREADER_H + +#include +#include +#include "../../../DesktopEditor/xml/include/xmlutils.h" + +namespace OFD +{ +class CXmlReader : public XmlUtils::CXmlLiteReader +{ + std::wstring GetTextValue(bool bIsAttribute = false); + std::string GetTextValueA(bool bIsAttribute = false); +public: + CXmlReader(); + + bool GetBoolean(bool bIsAttribute = false); + int GetInteger(bool bIsAttribute = false); + unsigned int GetUInteger(bool bIsAttribute = false); + double GetDouble(bool bIsAttribute = false); + std::vector GetArrayStrings(bool bIsAttribute = false); + std::vector GetArrayDoubles(bool bIsAttribute = false); +}; +} + +#endif // XMLREADER_H diff --git a/OFDFile/test/main.cpp b/OFDFile/test/main.cpp new file mode 100644 index 0000000000..92189f10ff --- /dev/null +++ b/OFDFile/test/main.cpp @@ -0,0 +1,35 @@ +#include "../OfdFile.h" +#include + +#include "../../DesktopEditor/common/Directory.h" +#include "../../DesktopEditor/common/File.h" +#include "../../DesktopEditor/graphics/pro/Fonts.h" +#include "../../DesktopEditor/fontengine/ApplicationFontsWorker.h" + +int main() +{ + // Check system fonts + CApplicationFontsWorker oWorker; + oWorker.m_sDirectory = NSFile::GetProcessDirectory() + L"/fonts_cache"; + oWorker.m_bIsNeedThumbnails = false; + + if (!NSDirectory::Exists(oWorker.m_sDirectory)) + NSDirectory::CreateDirectory(oWorker.m_sDirectory); + + NSFonts::IApplicationFonts* pFonts = oWorker.Check(); + + COFDFile oOfdFile(pFonts); + + oOfdFile.SetTempDirectory(L"temp"); + + if (oOfdFile.LoadFromFile(L"YOUR_PATH")) + std::cout << "GOOD" << std::endl; + else + std::cout << "BAD" << std::endl; + + oOfdFile.ConvertToRaster(0, L"result.png", 4); + + pFonts->Release(); + + return 0; +} diff --git a/OFDFile/test/test.pro b/OFDFile/test/test.pro new file mode 100644 index 0000000000..0d0f676f86 --- /dev/null +++ b/OFDFile/test/test.pro @@ -0,0 +1,30 @@ +QT -= core +QT -= gui + +TARGET = test +TEMPLATE = app + +CONFIG += console +CONFIG -= app_bundle +s +CORE_ROOT_DIR = $$PWD/../../ +PWD_ROOT_DIR = $$PWD + +include($$CORE_ROOT_DIR/Common/base.pri) +include($$CORE_ROOT_DIR/Common/3dParty/icu/icu.pri) + +ADD_DEPENDENCY(kernel, graphics, UnicodeConverter, OFDFile) + +win32 { +LIBS += -lgdi32 \ + -ladvapi32 \ + -luser32 \ + -lshell32 +} +linux-g++ | linux-g++-64 | linux-g++-32 { + LIBS += -lz +} + +SOURCES += main.cpp + +DESTDIR = $$PWD_ROOT_DIR/build/$$CORE_BUILDS_PLATFORM_PREFIX/$$CORE_BUILDS_CONFIGURATION_PREFIX diff --git a/PdfFile/PdfWriter.cpp b/PdfFile/PdfWriter.cpp index 94761cac2b..44656331e3 100644 --- a/PdfFile/PdfWriter.cpp +++ b/PdfFile/PdfWriter.cpp @@ -655,6 +655,8 @@ HRESULT CPdfWriter::CommandDrawTextCHAR(const LONG& lUnicode, const double& dX, unsigned int unUnicode = lUnicode; unsigned char* pCodes = EncodeString(&unUnicode, 1); + if (!pCodes) + return DrawTextToRenderer(NULL, 0, dX, dY, NSStringExt::CConverter::GetUnicodeFromUTF32(&unUnicode, 1)) ? S_OK : S_FALSE; return DrawText(pCodes, 2, dX, dY, UnicodePUA(unUnicode) ? NSStringExt::CConverter::GetUtf8FromUTF32(&unUnicode, 1) : "") ? S_OK : S_FALSE; } HRESULT CPdfWriter::CommandDrawText(const std::wstring& wsUnicodeText, const double& dX, const double& dY, const double& dW, const double& dH) @@ -674,7 +676,7 @@ HRESULT CPdfWriter::CommandDrawText(const std::wstring& wsUnicodeText, const dou delete[] pUnicodes; if (!pCodes) - return S_FALSE; + return DrawTextToRenderer(NULL, 0, dX, dY, wsUnicodeText) ? S_OK : S_FALSE; // Специальный случай для текста из Djvu, нам не нужно, чтобы он рисовался if (L"" == m_oFont.GetPath() && L"DjvuEmptyFont" == m_oFont.GetName()) @@ -3112,14 +3114,14 @@ bool CPdfWriter::DrawText(unsigned char* pCodes, const unsigned int& unLen, cons return true; } -bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY) +bool CPdfWriter::DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY, const std::wstring& wsUnicodeText) { // TODO pdf позволяет создание своего шрифта, но не следует это использовать для воссоздания шрифта запрещенного для редактирования или встраивания Aggplus::CGraphicsPathSimpleConverter simplifier; simplifier.SetRenderer(m_pRenderer); m_pFontManager->LoadFontByName(m_oFont.GetName(), m_oFont.GetSize(), (int)m_oFont.GetStyle(), 72.0, 72.0); PathCommandEnd(); - if (simplifier.PathCommandText2(L"", (const int*)unGid, unLen, m_pFontManager, dX, dY, 0, 0)) + if (simplifier.PathCommandText2(wsUnicodeText, (const int*)unGid, unLen, m_pFontManager, dX, dY, 0, 0)) { DrawPath(NULL, L"", c_nWindingFillMode); PathCommandEnd(); @@ -3717,6 +3719,11 @@ unsigned char* CPdfWriter::EncodeString(const unsigned int *pUnicodes, const uns ushCode = m_pFont->EncodeGID(pGIDs[unIndex], &pUnicodes[unIndex], 1); else ushCode = m_pFont->EncodeUnicode(pUnicodes[unIndex]); + if (ushCode == 0) + { + RELEASEARRAYOBJECTS(pCodes); + return NULL; + } pCodes[2 * unIndex + 0] = (ushCode >> 8) & 0xFF; pCodes[2 * unIndex + 1] = ushCode & 0xFF; @@ -3756,6 +3763,12 @@ unsigned char* CPdfWriter::EncodeGID(const unsigned int& unGID, const unsigned i return NULL; unsigned short ushCode = m_pFont->EncodeGID(unGID, pUnicodes, unUnicodesCount); + if (ushCode == 0) + { + RELEASEARRAYOBJECTS(pCodes); + return NULL; + } + pCodes[0] = (ushCode >> 8) & 0xFF; pCodes[1] = ushCode & 0xFF; return pCodes; diff --git a/PdfFile/PdfWriter.h b/PdfFile/PdfWriter.h index 98f4ba015a..3ca2de790d 100644 --- a/PdfFile/PdfWriter.h +++ b/PdfFile/PdfWriter.h @@ -226,7 +226,7 @@ private: PdfWriter::CImageDict* LoadImage(Aggplus::CImage* pImage, BYTE nAlpha); PdfWriter::CImageDict* DrawImage(Aggplus::CImage* pImage, const double& dX, const double& dY, const double& dW, const double& dH, const BYTE& nAlpha); bool DrawText(unsigned char* pCodes, const unsigned int& unLen, const double& dX, const double& dY, const std::string& sPUA); - bool DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY); + bool DrawTextToRenderer(const unsigned int* unGid, const unsigned int& unLen, const double& dX, const double& dY, const std::wstring& wsUnicodeText = L""); bool PathCommandDrawText(unsigned int* pUnicodes, unsigned int unLen, const double& dX, const double& dY, const unsigned int* pGids = NULL); int IsEmbeddedBase14(const std::wstring& wsFontName); bool GetBaseFont14(const std::wstring& wsFontName, int nBase14); diff --git a/PdfFile/SrcWriter/FontCidTT.cpp b/PdfFile/SrcWriter/FontCidTT.cpp index 22411d6cc8..d19a1b962b 100644 --- a/PdfFile/SrcWriter/FontCidTT.cpp +++ b/PdfFile/SrcWriter/FontCidTT.cpp @@ -339,9 +339,12 @@ namespace PdfWriter } memset((void *)pGlyphs, 0x00, m_nGlyphsCount * sizeof(unsigned char)); - for (auto oIt : m_mGlyphs) + if (m_nGlyphsCount >= m_mGlyphs.size()) { - pGlyphs[oIt.first] = 1; + for (auto oIt : m_mGlyphs) + { + pGlyphs[oIt.first] = 1; + } } *ppCodeToGid = pCodeToGID; @@ -539,6 +542,8 @@ namespace PdfWriter { m_vWidths.push_back(0); m_vGlypWidths.push_back(0); + m_vCodeToGid.back() = 0; + return 0; } return ushCode; diff --git a/X2tConverter/build/Qt/X2tConverter.pri b/X2tConverter/build/Qt/X2tConverter.pri index 685961ee4a..0cdc5af511 100644 --- a/X2tConverter/build/Qt/X2tConverter.pri +++ b/X2tConverter/build/Qt/X2tConverter.pri @@ -32,6 +32,7 @@ DEFINES += UNICODE \ DEFINES += PDFFILE_USE_DYNAMIC_LIBRARY DEFINES += XPS_USE_DYNAMIC_LIBRARY +DEFINES += OFD_USE_DYNAMIC_LIBRARY DEFINES += DJVU_USE_DYNAMIC_LIBRARY DEFINES += HTMLFILE_USE_DYNAMIC_LIBRARY DEFINES += UNICODECONVERTER_USE_DYNAMIC_LIBRARY @@ -130,7 +131,7 @@ LIBS += -L$$CORE_BUILDS_LIBRARIES_PATH -lCryptoPPLib #All dynamic libs -ADD_DEPENDENCY(graphics, kernel, UnicodeConverter, kernel_network, Fb2File, PdfFile, HtmlFile2, EpubFile, XpsFile, DjVuFile, doctrenderer, DocxRenderer, IWorkFile, HWPFile) +ADD_DEPENDENCY(graphics, kernel, UnicodeConverter, kernel_network, Fb2File, PdfFile, HtmlFile2, EpubFile, XpsFile, OFDFile, DjVuFile, doctrenderer, DocxRenderer, IWorkFile, HWPFile) ##################################################### # внешнее подключение сторонних библиотек diff --git a/X2tConverter/src/lib/pdf_image.h b/X2tConverter/src/lib/pdf_image.h index 569ea9fc73..8d2d776ae5 100644 --- a/X2tConverter/src/lib/pdf_image.h +++ b/X2tConverter/src/lib/pdf_image.h @@ -38,6 +38,7 @@ #include "../../../DocxRenderer/DocxRenderer.h" #include "../../../PdfFile/PdfFile.h" #include "../../../XpsFile/XpsFile.h" +#include "../../../OFDFile/OFDFile.h" #include "../../../OfficeUtils/src/ZipFolder.h" #include "common.h" @@ -416,6 +417,8 @@ namespace NExtractTools return new CXpsFile(pFonts); case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU: return new CDjVuFile(pFonts); + case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD: + return new COFDFile(pFonts); default: break; } @@ -1027,6 +1030,9 @@ namespace NExtractTools case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_XPS: pReader = new CXpsFile(pApplicationFonts); break; + case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_OFD: + pReader = new COFDFile(pApplicationFonts); + break; case AVS_OFFICESTUDIO_FILE_CROSSPLATFORM_DJVU: pReader = new CDjVuFile(pApplicationFonts); break;