diff --git a/XpsFile/XpsFileTest/XpsFileTest.cpp b/XpsFile/XpsFileTest/XpsFileTest.cpp index 50e9abbb86..dfc207bfa5 100644 --- a/XpsFile/XpsFileTest/XpsFileTest.cpp +++ b/XpsFile/XpsFileTest/XpsFileTest.cpp @@ -13,6 +13,7 @@ #include "../../DesktopEditor/fontengine/ApplicationFonts.h" #include +#include std::vector GetAllFilesInFolder(std::wstring wsFolder, std::wstring wsExt) { @@ -99,9 +100,15 @@ void ConvertFolderToPdf(const std::wstring& wsFolderPath) void main() { + clock_t oBeginTime = clock(); + //ConvertFolderToRaster(L"D:/Test Files//Xps//"); ConvertFolderToPdf(L"D:/Test Files//Xps//"); + clock_t oEndTime = clock(); + double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; + printf("%fseconds\n", dElapsedSecs); + char q; std::cin >> q; } diff --git a/XpsFile/XpsLib/ContextState.cpp b/XpsFile/XpsLib/ContextState.cpp index 809b43e608..133571d92e 100644 --- a/XpsFile/XpsLib/ContextState.cpp +++ b/XpsFile/XpsLib/ContextState.cpp @@ -6,35 +6,27 @@ namespace XPS { - CContextState::CContextState() : m_oCurrentTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0) + CContextState::CContextState(IRenderer* pRenderer) : m_oCurrentTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0), m_pRenderer(pRenderer) { m_lTransformStack.push_back(m_oCurrentTransform); } CContextState::~CContextState() { - } - void CContextState::AddFigure(const std::wstring& wsKey, const std::wstring& wsValue) - { - m_mFigures.insert(std::pair(wsKey, wsValue)); - } - std::wstring CContextState::GetFigure(const std::wstring& wsKey) - { - std::map::iterator oIter = m_mFigures.find(wsKey); - if (oIter != m_mFigures.end()) - return oIter->second; - - return L""; - } + m_vClipStack.clear(); + m_lTransformStack.clear(); + } void CContextState::PushTransform(const double arrTransform[6]) { Aggplus::CMatrix oTransform(arrTransform[0], arrTransform[1], arrTransform[2], arrTransform[3], arrTransform[4], arrTransform[5]); m_oCurrentTransform.Multiply(&oTransform); m_lTransformStack.push_back(m_oCurrentTransform); + SetTransformToRenderer(); } void CContextState::PopTransform() { m_lTransformStack.pop_back(); m_oCurrentTransform = m_lTransformStack.back(); + SetTransformToRenderer(); } double CContextState::NormalizeTransform() { @@ -46,13 +38,51 @@ namespace XPS oMatrix.sy /= dDet; oMatrix.shy /= dDet; + SetTransformToRenderer(); + return dDet; } - void CContextState::SetTransformToRenderer(IRenderer* pRenderer) + void CContextState::PushClip(const CWString& wsClip) { - pRenderer->SetTransform(m_oCurrentTransform.m_agg_mtx.sx, m_oCurrentTransform.m_agg_mtx.shy, - m_oCurrentTransform.m_agg_mtx.shx, m_oCurrentTransform.m_agg_mtx.sy, - xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.tx), xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.ty)); + m_vClipStack.push_back(wsClip); + SetClipToRenderer(wsClip); + } + void CContextState::PopClip() + { + m_vClipStack.pop_back(); + if (m_pRenderer) + { + m_pRenderer->BeginCommand(c_nResetClipType); + m_pRenderer->EndCommand(c_nResetClipType); + for (int nIndex = 0, nCount = m_vClipStack.size(); nIndex < nCount; nIndex++) + { + CWString wsClip = m_vClipStack.at(nIndex); + SetClipToRenderer(wsClip); + } + } + } + void CContextState::SetTransformToRenderer() + { + if (m_pRenderer) + { + m_pRenderer->SetTransform(m_oCurrentTransform.m_agg_mtx.sx, m_oCurrentTransform.m_agg_mtx.shy, + m_oCurrentTransform.m_agg_mtx.shx, m_oCurrentTransform.m_agg_mtx.sy, + xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.tx), xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.ty)); + } + } + void CContextState::SetClipToRenderer(const CWString& wsClip) + { + if (!wsClip.empty() && m_pRenderer) + { + m_pRenderer->PathCommandStart(); + m_pRenderer->BeginCommand(c_nClipType); + m_pRenderer->BeginCommand(c_nPathType); + bool bWinding = VmlToRenderer(wsClip.c_str(), m_pRenderer); + m_pRenderer->put_ClipMode(bWinding ? c_nClipRegionTypeWinding : c_nClipRegionTypeEvenOdd); + m_pRenderer->EndCommand(c_nPathType); + m_pRenderer->EndCommand(c_nClipType); + m_pRenderer->PathCommandEnd(); + } } } \ No newline at end of file diff --git a/XpsFile/XpsLib/ContextState.h b/XpsFile/XpsLib/ContextState.h index 0196dceefb..b770c60721 100644 --- a/XpsFile/XpsLib/ContextState.h +++ b/XpsFile/XpsLib/ContextState.h @@ -1,6 +1,8 @@ #ifndef _XPS_XPSLIB_CONTEXTSTATE_H #define _XPS_XPSLIB_CONTEXTSTATE_H +#include "Utils.h" + #include "../../DesktopEditor/graphics/Matrix.h" #include "../../DesktopEditor/graphics/IRenderer.h" @@ -13,21 +15,26 @@ namespace XPS { public: - CContextState(); + CContextState(IRenderer* pRenderer); ~CContextState(); - void AddFigure(const std::wstring& wsKey, const std::wstring& wsName); - std::wstring GetFigure(const std::wstring& wsKey); - void PushTransform(const double arrTransform[6]); - void PopTransform(); + void PushClip(const CWString& wsClip); + void PopClip(); + void PushTransform(const double arrTransform[6]); + void PopTransform(); double NormalizeTransform(); - void SetTransformToRenderer(IRenderer* pRenderer); - public: + private: - Aggplus::CMatrix m_oCurrentTransform; - std::list m_lTransformStack; - std::map m_mFigures; + void SetClipToRenderer(const CWString& wsClip); + void SetTransformToRenderer(); + + private: + + Aggplus::CMatrix m_oCurrentTransform; + std::list m_lTransformStack; + std::vector m_vClipStack; + IRenderer* m_pRenderer; }; } diff --git a/XpsFile/XpsLib/Document.cpp b/XpsFile/XpsLib/Document.cpp index 9f9f660357..b922ca62a5 100644 --- a/XpsFile/XpsLib/Document.cpp +++ b/XpsFile/XpsLib/Document.cpp @@ -249,5 +249,24 @@ namespace XPS } m_mPages.clear(); m_oFontList.Clear(); + + for (std::map::iterator oIter = m_mStaticResources.begin(); oIter != m_mStaticResources.end(); oIter++) + { + if (oIter->second) + delete oIter->second; + } + m_mStaticResources.clear(); + } + CStaticResource* CDocument::GetStaticResource(const std::wstring& wsPath) + { + for (auto oIt : m_mStaticResources) + { + if (oIt.first == wsPath) + return oIt.second; + } + + CStaticResource* pStaticResource = new CStaticResource(wsPath); + m_mStaticResources.insert(std::pair(wsPath, pStaticResource)); + return pStaticResource; } } \ No newline at end of file diff --git a/XpsFile/XpsLib/Document.h b/XpsFile/XpsLib/Document.h index c9841449a4..e42af2df63 100644 --- a/XpsFile/XpsLib/Document.h +++ b/XpsFile/XpsLib/Document.h @@ -4,6 +4,7 @@ #include "FontList.h" #include "Page.h" #include +#include #define UNICODE #define _UNICODE @@ -15,6 +16,8 @@ namespace XPS { + class CPath; + class CStaticResource; class CDocument { public: @@ -26,13 +29,109 @@ namespace XPS void GetPageSize(int nPageIndex, int& nW, int& nH); void DrawPage(int nPageIndex, IRenderer* pRenderer, bool* pbBreak); void Close(); + CStaticResource* GetStaticResource(const std::wstring& wsPath); private: - std::wstring m_wsPath; - std::map m_mPages; - CFontList m_oFontList; - CFontManager* m_pFontManager; + std::wstring m_wsPath; + std::map m_mPages; + CFontList m_oFontList; + CFontManager* m_pFontManager; + std::map m_mStaticResources; + }; + + class CStaticResource + { + public: + CStaticResource(const std::wstring& wsPath) + { + clock_t oBeginTime = clock(); + + XmlUtils::CXmlLiteReader oReader; + + if (!oReader.FromFile(wsPath)) + return; + + Parse(oReader); + + clock_t oEndTime = clock(); + double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; + printf("\n\nSTATIC RESOURCE %S %fseconds\n\n", wsPath.c_str() , dElapsedSecs); + } + CStaticResource(XmlUtils::CXmlLiteReader& oReader) + { + if (oReader.IsEmptyNode()) + return; + + Parse(oReader); + } + ~CStaticResource() + { + } + const wchar_t* Get(const wchar_t* wsKey) + { + CWString _wsKey((wchar_t*)wsKey, false); + std::map::iterator oIter = m_mFigures.find(_wsKey); + if (oIter != m_mFigures.end()) + return oIter->second.c_str(); + + return NULL; + } + const wchar_t* Get(CWString wsKey) + { + std::map::iterator oIter = m_mFigures.find(wsKey); + if (oIter != m_mFigures.end()) + return oIter->second.c_str(); + + return NULL; + } + + private: + + void Parse(XmlUtils::CXmlLiteReader& oReader) + { + CWString wsNodeName; + CWString wsAttrName; + int nCurDepth = oReader.GetDepth(); + while (oReader.ReadNextSiblingNode(nCurDepth)) + { + wsNodeName = oReader.GetName(); + if (wsNodeName == L"PathGeometry") + { + CWString wsKey, wsValue; + + if (oReader.MoveToFirstAttribute()) + { + wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"x:Key") + wsKey.create(oReader.GetText(), true); + else if (wsAttrName == L"Figures") + wsValue.create(oReader.GetText(), true); + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + + oReader.MoveToElement(); + } + + if (!wsKey.empty() && !wsValue.empty()) + Add(wsKey, wsValue); + } + } + } + void Add(const CWString& wsKey, const CWString& wsValue) + { + m_mFigures.insert(std::pair(wsKey, wsValue)); + } + + private: + + std::map m_mFigures; }; } diff --git a/XpsFile/XpsLib/Page.cpp b/XpsFile/XpsLib/Page.cpp index d1c0f86ac5..2a1ca24d7f 100644 --- a/XpsFile/XpsLib/Page.cpp +++ b/XpsFile/XpsLib/Page.cpp @@ -16,143 +16,6 @@ namespace XPS { - static inline void PageCommandL(std::vector& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos) - { - dCurX = GetDouble(arrElements[nPos + 1]); - dCurY = GetDouble(arrElements[nPos + 2]); - nPos += 2; - pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - } - static inline void PageCommandA(std::vector& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos) - { - Aggplus::CMatrix tmatx, rmatx, smatx, itmatx, irmatx, ismatx; - double x_cur_temp = dCurX; - double y_cur_temp = dCurY; - double x_end = GetDouble(arrElements[nPos + 6]); - double y_end = GetDouble(arrElements[nPos + 7]); - - tmatx.Translate(-dCurX, -dCurY); - tmatx.TransformPoint(x_cur_temp, y_cur_temp); - tmatx.TransformPoint(x_end, y_end); - - double angle = GetDouble(arrElements[nPos + 3]); - rmatx.Rotate(-angle); - rmatx.TransformPoint(x_cur_temp, y_cur_temp); - rmatx.TransformPoint(x_end, y_end); - - double rx = GetDouble(arrElements[nPos + 1]); - double ry = GetDouble(arrElements[nPos + 2]); - smatx.Scale(ry / rx, 1); - smatx.TransformPoint(x_cur_temp, y_cur_temp); - smatx.TransformPoint(x_end, y_end); - - double mid_x = (x_cur_temp + x_end) / 2.0, mid_y = (y_cur_temp + y_end) / 2.0; - double vect_x = x_end - x_cur_temp, vect_y = y_end - y_cur_temp; - double length = sqrt(vect_x * vect_x + vect_y * vect_y); - double halfChord = length / 2.0; - bool isLarge = GetBool(arrElements[nPos + 4]); - bool isCCW = !GetBool(arrElements[nPos + 5]); - double rotated_x, rotated_y; - - if (isLarge == isCCW) - { - rotated_x = -vect_y; - rotated_y = vect_x; - } - else - { - rotated_x = vect_y; - rotated_y = -vect_x; - } - - rotated_x = rotated_x / length; - rotated_y = rotated_y / length; - - double centerDistance = sqrt(max(ry * ry - halfChord * halfChord, 0)); - double center_x = mid_x + centerDistance * rotated_x, center_y = mid_y + centerDistance * rotated_y; - - double angle1 = atan2(y_cur_temp - center_y, x_cur_temp - center_x); - double angle2 = atan2(y_end - center_y, x_end - center_x); - - if ((!isCCW) && (abs(y_end - center_y) < 0.000001) && (x_end - center_x < 0)) - angle2 = -M_PI; - if ((isCCW) && (abs(y_cur_temp - center_y) < 0.000001) && (x_cur_temp - center_x < 0)) - angle1 = -M_PI; - - if (isLarge == (abs(angle2 - angle1) < M_PI)) - { - if (angle1 < angle2) - angle1 += 2 * M_PI; - else - angle2 += 2 * M_PI; - } - if (abs(angle2 - angle1) == M_PI) - { - if ((angle1 < angle2) && (isCCW) && (angle1 != -M_PI) && (angle1 != 0.0) && (angle1 != M_PI)) - angle1 += 2 * M_PI; - } - - itmatx.Translate(dCurX, dCurY); - irmatx.Rotate(angle); - ismatx.Scale(rx / ry, 1); - - int max = (int)((4 * (rx + ry) * abs(angle2 - angle1) / (2 * M_PI)) / 1/*tolerance*/); - - double x, y; - for (int counter = 0; counter <= max; counter++) - { - double angle_cur = ((max - counter) * angle1 + counter * angle2) / max; - x = center_x + ry * cos(angle_cur); - y = center_y + ry * sin(angle_cur); - - // Transform the point back - ismatx.TransformPoint(x, y); - irmatx.TransformPoint(x, y); - itmatx.TransformPoint(x, y); - pRenderer->PathCommandLineTo(xpsUnitToMM(x), xpsUnitToMM(y)); - } - - dCurX = x; - dCurY = y; - nPos += 7; - } - static inline void PageCommandC(std::vector& arrElements, double& dCurX, double& dCurY, double& dCpX, double& dCpY, IRenderer* pRenderer, int& nPos) - { - dCpX = GetDouble(arrElements[nPos + 3]); - dCpY = GetDouble(arrElements[nPos + 4]); - dCurX = GetDouble(arrElements[nPos + 5]); - dCurY = GetDouble(arrElements[nPos + 6]); - - pRenderer->PathCommandCurveTo(xpsUnitToMM(GetDouble(arrElements[nPos + 1])), xpsUnitToMM(GetDouble(arrElements[nPos + 2])), xpsUnitToMM(dCpX), xpsUnitToMM(dCpY), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - nPos += 6; - } - static inline void PageCommandQ(std::vector& arrElements, double& dCurX, double& dCurY, IRenderer* pRenderer, int& nPos) - { - double x1 = 2.0 * GetDouble(arrElements[nPos + 1]); - double y1 = 2.0 * GetDouble(arrElements[nPos + 2]); - double x2 = GetDouble(arrElements[nPos + 3]); - double y2 = GetDouble(arrElements[nPos + 4]); - - pRenderer->PathCommandCurveTo(xpsUnitToMM((dCurX + x1) / 3.0), xpsUnitToMM((dCurY + y1) / 3.0), xpsUnitToMM((x1 + x2) / 3.0), xpsUnitToMM((y1 + y2) / 3.0), xpsUnitToMM(x2), xpsUnitToMM(y2)); - dCurX = x2; - dCurY = y2; - nPos += 4; - } - static inline void PageCommandS(std::vector& arrElements, double& dCurX, double& dCurY, double& dCpX, double& dCpY, IRenderer* pRenderer, int& nPos) - { - dCpX = 2 * dCurX - dCpX; - dCpY = 2 * dCurY - dCpY; - - dCurX = GetDouble(arrElements[nPos + 3]); - dCurY = GetDouble(arrElements[nPos + 4]); - pRenderer->PathCommandCurveTo(xpsUnitToMM(dCpX), xpsUnitToMM(dCpY), - xpsUnitToMM(GetDouble(arrElements[nPos + 1])), xpsUnitToMM(GetDouble(arrElements[nPos + 2])), - xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - - dCpX = GetDouble(arrElements[nPos + 1]); - dCpY = GetDouble(arrElements[nPos + 2]); - nPos += 4; - } Page::Page(const std::wstring& wsPagePath, const std::wstring& wsRootPath, CFontList* pFontList, CFontManager* pFontManager, CDocument* pDocument) { m_wsPagePath = wsPagePath; @@ -160,9 +23,16 @@ namespace XPS m_pFontList = pFontList; m_pFontManager = pFontManager; m_pDocument = pDocument; + + m_pStaticResource = NULL; + m_bDeleteStaticResource = false; + + m_nCounter = 0; } Page::~Page() { + if (m_bDeleteStaticResource) + RELEASEOBJECT(m_pStaticResource); } void Page::GetSize(int& nW, int& nH) const { @@ -209,124 +79,29 @@ namespace XPS if (L"FixedPage" != wsNodeName) return; - CContextState oState; + CContextState oState(pRenderer); DrawCanvas(oReader, pRenderer, &oState, pbBreak); - - - - - /*XmlUtils::CXmlNode oNode; - - - clock_t oBeginTime = clock(); - - if (!oNode.FromXmlFile(m_wsPagePath.c_str())) - return; - - clock_t oEndTime = clock(); - double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - printf("%S %fseconds\n", m_wsPagePath.c_str(), dElapsedSecs); - - if (L"FixedPage" != oNode.GetName()) - return; - - CContextState oState; - - XmlUtils::CXmlNode oNodeResources; - if (oNode.GetNode(L"FixedPage.Resources", oNodeResources)) - { - XmlUtils::CXmlNode oNodeDictionary; - if (oNodeResources.GetNode(L"ResourceDictionary", oNodeDictionary)) - { - std::wstring wsXmlSource = oNodeDictionary.GetAttribute(L"Source"); - if (L"" != wsXmlSource) - { - std::wstring wsPath = m_wsRootPath + wsXmlSource; - - XmlUtils::CXmlNode oNodeSource; - - clock_t oBeginTime = clock(); - - oNodeSource.FromXmlFile(wsPath.c_str()); - - clock_t oEndTime = clock(); - double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - printf("%S %fseconds\n", wsPath.c_str(), dElapsedSecs); - - if (oNodeSource.IsValid()) - { - XmlUtils::CXmlNodes arrNodes; - if (oNodeSource.GetNodes(L"PathGeometry", arrNodes)) - { - for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++) - { - XmlUtils::CXmlNode oNode; - arrNodes.GetAt(nIndex, oNode); - std::wstring wsKey = oNode.GetAttribute(L"x:Key"); - std::wstring wsValue = oNode.GetAttribute(L"Figures"); - - wsKey = L"{StaticResource " + wsKey + L"}"; - oState.AddFigure(wsKey, wsValue); - } - } - } - } - else - { - XmlUtils::CXmlNodes arrNodes; - if (oNodeDictionary.GetNodes(L"PathGeometry", arrNodes)) - { - for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++) - { - XmlUtils::CXmlNode oNode; - arrNodes.GetAt(nIndex, oNode); - - std::wstring wsKey = oNode.GetAttribute(L"x:Key"); - std::wstring wsValue = oNode.GetAttribute(L"Figures"); - - wsKey = (L"{StaticResource " + wsKey + L"}"); - oState.AddFigure(wsKey, wsValue); - } - } - } - } - } - - DrawCanvas(oNode, pRenderer, &oState, pbBreak); - return;*/ } void Page::DrawCanvas(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak) { - std::wstring wsClip; - ReadAttribute(oReader, L"Clip", wsClip); - bool bClip = false; - if (L"" != wsClip) + bool bTransform = false, bClip = false; + if (oReader.MoveToFirstAttribute()) { - std::wstring wsValue = pState->GetFigure(wsClip); - if (L"" != wsValue) - wsClip = wsValue; + CWString wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"Clip") + bClip = ClipToRenderer(oReader.GetText(), pState); + else if (wsAttrName == L"RenderTransform") + bTransform = TransformToRenderer(oReader.GetText(), pState); - bClip = true; - pRenderer->PathCommandStart(); - pRenderer->BeginCommand(c_nClipType); - pRenderer->put_ClipMode(0); - pRenderer->BeginCommand(c_nPathType); + if (!oReader.MoveToNextAttribute()) + break; - VmlToRenderer(wsClip, pRenderer); - - pRenderer->EndCommand(c_nPathType); - pRenderer->EndCommand(c_nClipType); - pRenderer->PathCommandEnd(); - } - - std::wstring wsTransform; - ReadAttribute(oReader, L"RenderTransform", wsTransform); - bool bTransform = false; - if (L"" != wsTransform) - { - bTransform = true; - TransformToRenderer(wsTransform, pRenderer, pState); + wsAttrName = oReader.GetName(); + } } + oReader.MoveToElement(); if (oReader.IsEmptyNode()) return; @@ -353,10 +128,7 @@ namespace XPS else if (L"Canvas.RenderTransform" == wsNodeName) { if (!bTransform) - { - CanvasTransform(oReader, pRenderer, pState); - bTransform = true; - } + bTransform = ReadTransform(oReader, pRenderer, pState); } else if (L"Path" == wsNodeName) { @@ -368,13 +140,10 @@ namespace XPS } if (bClip) - { - pRenderer->BeginCommand(c_nResetClipType); - pRenderer->EndCommand(c_nResetClipType); - } + pState->PopClip(); if (bTransform) - ResetTransform(pRenderer, pState); + pState->PopTransform(); } void Page::ReadPageResources(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { @@ -393,387 +162,48 @@ namespace XPS if (!wsSource.empty()) { std::wstring wsPath = m_wsRootPath + wsSource; - - XmlUtils::CXmlLiteReader oSourceReader; - clock_t oBeginTime = clock(); - - if (!oSourceReader.FromFile(wsPath)) - return; - - std::wstring wsNodeText; - while (oSourceReader.ReadNextNode()) - { - wsNodeName = oSourceReader.GetName(); - if (L"PathGeometry" == wsNodeName) - { - std::wstring wsKey, wsValue; - - if (oSourceReader.MoveToFirstAttribute()) - { - std::wstring wsAttrName = oSourceReader.GetName(); - while (!wsAttrName.empty()) - { - if (L"x:Key" == wsAttrName) - wsKey = oSourceReader.GetText(); - else if (L"Figures" == wsAttrName) - wsValue = oSourceReader.GetText(); - - if (!oSourceReader.MoveToNextAttribute()) - break; - - wsAttrName = oSourceReader.GetName(); - } - - oSourceReader.MoveToElement(); - } - - wsKey = L"{StaticResource " + wsKey + L"}"; - pState->AddFigure(wsKey, wsValue); - } - } - - clock_t oEndTime = clock(); - double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - printf("%S %fseconds\n", wsPath.c_str(), dElapsedSecs); + m_pStaticResource = m_pDocument->GetStaticResource(wsPath); + m_bDeleteStaticResource = false; } else { - if (oReader.IsEmptyNode()) - return; - - int nPathDepth = oReader.GetDepth(); - while (oReader.ReadNextSiblingNode(nPathDepth)) - { - wsNodeName = oReader.GetName(); - if (L"PathGeometry" == wsNodeName) - { - std::wstring wsKey, wsValue; - ReadAttribute(oReader, L"x:Key", wsKey); - ReadAttribute(oReader, L"Figures", wsValue); - wsKey = L"{StaticResource " + wsKey + L"}"; - pState->AddFigure(wsKey, wsValue); - } - } + m_pStaticResource = new CStaticResource(oReader); + m_bDeleteStaticResource = true; } } } - } - void Page::DrawCanvas(XmlUtils::CXmlNode& oCanvasNode, IRenderer* pRenderer, CContextState* pState, bool* pbBreak) + } + bool Page::ClipToRenderer(const wchar_t* wsString, CContextState* pState) { - bool bClip = false; - std::wstring wsClip = oCanvasNode.GetAttribute(L"Clip", L""); - if (L"" != wsClip) + CWString wsClip; + wsClip.create(wsString, true); + if (!wsClip.empty()) { - std::wstring wsValue = pState->GetFigure(wsClip); - if (L"" != wsValue) - wsClip = wsValue; - - bClip = true; - pRenderer->PathCommandStart(); - pRenderer->BeginCommand(c_nClipType); - pRenderer->put_ClipMode(0); - pRenderer->BeginCommand(c_nPathType); - - VmlToRenderer(wsClip, pRenderer); - - pRenderer->EndCommand(c_nPathType); - pRenderer->EndCommand(c_nClipType); - pRenderer->PathCommandEnd(); - } - - bool bTransform = false; - std::wstring wsTransform = oCanvasNode.GetAttribute(L"RenderTransform", L""); - if (L"" != wsTransform) - { - bTransform = true; - TransformToRenderer(wsTransform, pRenderer, pState); - } - - XmlUtils::CXmlNodes arrNodes; - XmlUtils::CXmlNode oNode; - std::wstring wsNodeName; - oCanvasNode.GetNodes(L"*", arrNodes); - for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++) - { - arrNodes.GetAt(nIndex, oNode); - wsNodeName = oNode.GetName(); - wsNodeName = RemoveNamespace(wsNodeName); - - if (L"Glyphs" == wsNodeName) - DrawGlyph(oNode, pRenderer, pState); - else if (L"Canvas" == wsNodeName) - DrawCanvas(oNode, pRenderer, pState, pbBreak); - else if (L"Canvas.RenderTransform" == wsNodeName) + if ('{' == wsClip[0] && wsClip.size() >= 17) { - if (!bTransform) - { - CanvasTransform(oNode, pRenderer, pState); - bTransform = true; - } - } - else if (L"Path" == wsNodeName) - DrawPath(oNode, pRenderer, pState); - - if (NULL != pbBreak) - { - if (*pbBreak) - return; + CWString wsKey((wchar_t*)(wsClip.c_str() + 16), false, wsClip.size() - 17); + wsClip = m_pStaticResource->Get(wsKey.c_str()); } + pState->PushClip(wsClip); + return true; } - - if (bClip) - { - pRenderer->BeginCommand(c_nResetClipType); - pRenderer->EndCommand(c_nResetClipType); - } - - if (bTransform) - ResetTransform(pRenderer, pState); + return false; } - bool Page::VmlToRenderer(std::wstring& wsString, IRenderer* pRenderer) + bool Page::TransformToRenderer(const wchar_t* wsString, CContextState* pState) { - bool bResult = false; - double dCurX = 0.0, dCurY = 0.0; - double dCpX = 0.0, dCpY = 0.0; - - bool bPrevCommandIsCurve = false; - - PrepareVmlString(wsString); - std::vector arrElements = NSString::Split(wsString, L" ,", false); - - int nElementsCount = (int)arrElements.size(); - for (int nPos = 0; nPos < nElementsCount; nPos++) + CWString wsTransform = wsString; + if (!wsTransform.empty()) { - bPrevCommandIsCurve = false; - if (L"F" == arrElements[nPos]) - { - bResult = GetBool(arrElements[nPos + 1]); - } - else if (L"M" == arrElements[nPos] || L"m" == arrElements[nPos]) - { - dCurX = GetDouble(arrElements[nPos + 1]); - dCurY = GetDouble(arrElements[nPos + 2]); - nPos += 2; - pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - } - else if (L"L" == arrElements[nPos] || L"l" == arrElements[nPos]) - { - PageCommandL(arrElements, dCurX, dCurY, pRenderer, nPos); + std::vector arrElements = NSStringExt::Split(wsString, L','); + double arrRes[6] ={ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; + for (int nIndex = 0, nCount = min(6, arrElements.size()); nIndex < nCount; nIndex++) + arrRes[nIndex] = GetDouble(arrElements[nIndex]); - if (nPos + 2 < nElementsCount) - { - while ((nPos + 2 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0]))) - { - PageCommandL(arrElements, dCurX, dCurY, pRenderer, nPos); - } - } - } - else if (L"A" == arrElements[nPos] || L"a" == arrElements[nPos]) - { - PageCommandA(arrElements, dCurX, dCurY, pRenderer, nPos); - - if (nPos + 7 < nElementsCount) - { - while ((nPos + 7 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0]))) - { - PageCommandA(arrElements, dCurX, dCurY, pRenderer, nPos); - } - } - } - else if (L"H" == arrElements[nPos] || L"h" == arrElements[nPos]) - { - dCurX = GetDouble(arrElements[nPos + 1]); - pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - nPos += 1; - } - else if (L"V" == arrElements[nPos] || L"v" == arrElements[nPos]) - { - dCurY = GetDouble(arrElements[nPos + 1]); - pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); - nPos += 1; - } - else if (L"C" == arrElements[nPos] || L"c" == arrElements[nPos]) - { - PageCommandC(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos); - - if (nPos + 6 < nElementsCount) - { - while ((nPos + 6 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0]))) - { - PageCommandC(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos); - } - } - bPrevCommandIsCurve = true; - } - else if (L"Q" == arrElements[nPos] || L"q" == arrElements[nPos]) - { - PageCommandQ(arrElements, dCurX, dCurY, pRenderer, nPos); - - if (nPos + 4 < nElementsCount) - { - while ((nPos + 4 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0]))) - { - PageCommandQ(arrElements, dCurX, dCurY, pRenderer, nPos); - } - } - } - else if (L"S" == arrElements[nPos] || L"s" == arrElements[nPos]) - { - if ((!bPrevCommandIsCurve) || (nPos == 0)) - { - dCpX = dCurX; - dCpY = dCurY; - } - - PageCommandS(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos); - - if (nPos + 4 < nElementsCount) - { - while ((nPos + 4 < nElementsCount) && (!IsAlpha(arrElements[nPos + 1][0]))) - { - PageCommandS(arrElements, dCurX, dCurY, dCpX, dCpY, pRenderer, nPos); - } - } - bPrevCommandIsCurve = true; - } - else if (L"Z" == arrElements[nPos] || L"Z" == arrElements[nPos]) - { - pRenderer->PathCommandClose(); - } + pState->PushTransform(arrRes); + return true; } - - return bResult; - } - void Page::PrepareVmlString(std::wstring& wsString) - { - const wchar_t* wsVml = L"FMLHVCQSAZfmlhvcqsaz"; - - std::wstring wsResult; - - int nPos = wsString.find(wsVml); - while (std::wstring::npos != nPos) - { - wsResult += wsString.substr(0, nPos); - wsResult += L" "; - wsResult += wsString.substr(nPos, 1); - wsResult += L" "; - wsString.erase(0, nPos + 1); - nPos = wsString.find(wsVml); - } - wsResult += wsString; - wsString = wsResult; - } - void Page::TransformToRenderer(const std::wstring& wsString, IRenderer* pRenderer, CContextState* pState) - { - std::vector arrElements = NSString::Split(wsString, L','); - - double arrRes[6] ={ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }; - for (int nIndex = 0, nCount = min(6, arrElements.size()); nIndex < nCount; nIndex++) - arrRes[nIndex] = GetDouble(arrElements[nIndex]); - - pState->PushTransform(arrRes); - pState->SetTransformToRenderer(pRenderer); - } - void Page::ResetTransform(IRenderer* pRenderer, CContextState* pState) - { - pState->PopTransform(); - pState->SetTransformToRenderer(pRenderer); - } - void Page::DrawGlyph(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState) - { - std::wstring wsFontPath = oRootNode.GetAttribute(L"FontUri", L""); - if (L"" != wsFontPath) - { - std::wstring wsFontName = GetFileName(wsFontPath); - wsFontPath = m_wsRootPath + L"/" + wsFontPath; - std::wstring wsExt = GetFileExtension(wsFontPath); - NSString::ToLower(wsExt); - if(L"odttf" == wsExt) - { - NSString::ToLower(wsFontName); - m_pFontList->Check(wsFontName, wsFontPath); - } - wsFontPath = NormalizePath(wsFontPath); - pRenderer->put_FontPath(wsFontPath); - } - - int nBgr, nAlpha; - std::wstring wsFontColor = oRootNode.GetAttribute(L"Fill", L"#FF000000"); - GetBgra(wsFontColor, nBgr, nAlpha); - pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1(nAlpha); - pRenderer->put_BrushType(c_BrushTypeSolid); - - std::wstring wsFontStyle = oRootNode.GetAttribute(L"StyleSimulations", L""); - if (L"ItalicSimulation" == wsFontStyle) - pRenderer->put_FontStyle(0x02); - else if (L"BoldSimulation" == wsFontStyle) - pRenderer->put_FontStyle(0x01); - else if (L"BoldItalicSimulation" == wsFontStyle) - pRenderer->put_FontStyle(0x03); - - std::wstring wsFontSize = oRootNode.GetAttribute(L"FontRenderingEmSize"); - double dFontSize = GetDouble(wsFontSize); - - bool bTransform = false; - std::wstring wsTransform = oRootNode.GetAttribute(L"RenderTransform", L""); - if(L"" != wsTransform) - { - TransformToRenderer(wsTransform, pRenderer, pState); - bTransform = true; - - if(dFontSize < 5) - { - double dDet = pState->NormalizeTransform(); - dFontSize *= dDet; - pState->SetTransformToRenderer(pRenderer); - } - } - pRenderer->put_FontSize(dFontSize * 0.75); - - std::wstring wsText = oRootNode.GetAttribute(L"UnicodeString", L""); - std::wstring wsTextX = oRootNode.GetAttribute(L"OriginX"); - std::wstring wsTextY = oRootNode.GetAttribute(L"OriginY"); - - int nTextLen = wsText.length(); - double dX = GetDouble(wsTextX); - double dY = GetDouble(wsTextY); - - std::wstring wsChar = wsText.substr(0, 1); - - std::wstring wsIndicies = oRootNode.GetAttribute(L"Indices", L""); - std::vector> arrElements = Split(wsIndicies, L';', L','); - - m_pFontManager->LoadFontFromFile(wsFontPath, 0, (float)(dFontSize * 0.75), 96, 96); - for(int nIndex = 0; nIndex < nTextLen - 1; nIndex++) - { - if (nIndex >= arrElements.size()) - arrElements.push_back(std::vector()); - - pRenderer->CommandDrawText(wsChar, xpsUnitToMM(dX), xpsUnitToMM(dY), 0, 0, 0); - - if (arrElements.at(nIndex).size() >= 2) - { - dX += GetDouble(arrElements.at(nIndex).at(1)) * dFontSize / 100.0; - } - else - { - m_pFontManager->LoadString1(wsChar, 0, 0); - TBBox oBox = m_pFontManager->MeasureString2(); - dX += (oBox.fMaxX - oBox.fMinX); - } - - wsChar = wsText.substr(nIndex + 1, 1); - } - - if (nTextLen > 0) - { - pRenderer->CommandDrawText(wsChar, xpsUnitToMM(dX), xpsUnitToMM(dY), 0, 0, 0); - } - - if (bTransform) - ResetTransform(pRenderer, pState); + return false; } void Page::DrawGlyph(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { @@ -797,10 +227,10 @@ namespace XPS std::wstring wsFontName = GetFileName(wsFontPath); wsFontPath = m_wsRootPath + L"/" + wsFontPath; std::wstring wsExt = GetFileExtension(wsFontPath); - NSString::ToLower(wsExt); + NSStringExt::ToLower(wsExt); if (L"odttf" == wsExt) { - NSString::ToLower(wsFontName); + NSStringExt::ToLower(wsFontName); m_pFontList->Check(wsFontName, wsFontPath); } wsFontPath = NormalizePath(wsFontPath); @@ -808,7 +238,6 @@ namespace XPS } else if (L"Fill" == wsAttrName) { - int nBgr, nAlpha; std::wstring wsFontColor = oReader.GetText(); ReadAttribute(oReader, L"Fill", wsFontColor); GetBgra(wsFontColor, nBgr, nAlpha); @@ -833,14 +262,11 @@ namespace XPS std::wstring wsTransform = oReader.GetText(); if (!wsTransform.empty()) { - TransformToRenderer(wsTransform, pRenderer, pState); - bTransform = true; - + bTransform = TransformToRenderer(wsTransform.c_str(), pState); if (dFontSize < 5) { double dDet = pState->NormalizeTransform(); dFontSize *= dDet; - pState->SetTransformToRenderer(pRenderer); } } } @@ -908,16 +334,9 @@ namespace XPS } if (bTransform) - ResetTransform(pRenderer, pState); + pState->PopTransform(); } - void Page::CanvasTransform(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState) - { - XmlUtils::CXmlNode oTransformNode; - oRootNode.GetNode(L"MatrixTransform", oTransformNode); - std::wstring wsMatrix = oTransformNode.GetAttribute(L"Matrix"); - TransformToRenderer(wsMatrix, pRenderer, pState); - } - void Page::CanvasTransform(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) + bool Page::ReadTransform(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { std::wstring wsNodeName; int nCurDepth = oReader.GetDepth(); @@ -930,92 +349,30 @@ namespace XPS { std::wstring wsMatrix; ReadAttribute(oReader, L"Matrix", wsMatrix); - TransformToRenderer(wsMatrix, pRenderer, pState); - break; - } - } - } - void Page::DrawPath(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer, CContextState* pState) - { - bool bTransform = false; - std::wstring wsTransform = oRootNode.GetAttribute(L"RenderTransform", L""); - if (L"" != wsTransform) - { - TransformToRenderer(wsTransform, pRenderer, pState); - bTransform = true; - } - - int nAlpha, nBgr; - std::wstring wsStrokeColor = oRootNode.GetAttribute(L"Stroke", L"#00FFFFFF"); - std::wstring wsPenSize = oRootNode.GetAttribute(L"StrokeThickness", L"1.0"); - GetBgra(wsStrokeColor, nBgr, nAlpha); - pRenderer->put_PenColor(nBgr & 0x00FFFFFF); - pRenderer->put_PenAlpha(nAlpha); - pRenderer->put_PenSize(xpsUnitToMM(GetDouble(wsPenSize))); - - std::wstring wsFill = oRootNode.GetAttribute(L"Fill"); - if (L"" != wsFill) - { - GetBgra(wsFill, nBgr, nAlpha); - pRenderer->put_BrushType(c_BrushTypeSolid); - pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1(nAlpha); - } - else - { - XmlUtils::CXmlNode oFillNode; - if (oRootNode.GetNode(L"Path.Fill", oFillNode)) - FillToRenderer(oFillNode, pRenderer); - else - { - pRenderer->put_BrushAlpha1(0); - pRenderer->put_BrushAlpha2(0); + return TransformToRenderer(wsMatrix.c_str(), pState); } } - std::wstring wsData = oRootNode.GetAttribute(L"Data"); - if (L"" == wsData) - { - GetDataFromNode(wsData, oRootNode); - } - - if (L'{' == wsData[0]) - { - std::wstring wsValue = pState->GetFigure(wsData); - if (L"" != wsValue) - wsData = wsValue; - else - { - if (bTransform) - ResetTransform(pRenderer, pState); - - return; - } - } - - pRenderer->BeginCommand(c_nPathType); - pRenderer->PathCommandStart(); - - bool bWindingFillMode = false; - if (L'{' != wsData[0]) - bWindingFillMode = VmlToRenderer(wsData, pRenderer); - - int nFillMode = bWindingFillMode ? c_nWindingFillMode | c_nStroke : c_nEvenOddFillMode | c_nStroke; - pRenderer->DrawPath(nFillMode); - - pRenderer->EndCommand(c_nPathType); - pRenderer->PathCommandEnd(); - - if (bTransform) - ResetTransform(pRenderer, pState); + return false; } void Page::DrawPath(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { - bool bTransform = false; + bool bTransform = false, bClip = false; bool bFillSetted = false; double dPenSize = 1.0; std::wstring wsData; bool bStroke = false; + + BYTE nDashCap = Aggplus::LineCapFlat; + BYTE nStartCap = Aggplus::LineCapFlat; + BYTE nEndCap = Aggplus::LineCapFlat; + BYTE nJoinStyle = Aggplus::LineJoinMiter; + double dMiter = 10.0; + + double* pDashPattern = NULL; + LONG lDashPatternSize = 0; + double dDashOffset = 0.0; + if (oReader.MoveToFirstAttribute()) { std::wstring wsAttrName = oReader.GetName(); @@ -1023,12 +380,11 @@ namespace XPS { if (L"RenderTransform" == wsAttrName) { - std::wstring wsTransform = oReader.GetText(); - if (!wsTransform.empty()) - { - TransformToRenderer(wsTransform, pRenderer, pState); - bTransform = true; - } + bTransform = TransformToRenderer(oReader.GetText(), pState); + } + else if (L"Clip" == wsAttrName) + { + bClip = ClipToRenderer(oReader.GetText(), pState); } else if (L"Stroke" == wsAttrName) { @@ -1044,6 +400,56 @@ namespace XPS std::wstring wsPenSize = oReader.GetText(); dPenSize = GetDouble(wsPenSize); } + else if (L"StrokeDashArray" == wsAttrName) + { + std::wstring wsDashArray = oReader.GetText(); + std::vector arrDashArray = NSStringExt::Split(wsDashArray, ' '); + int nDashArrayCount = arrDashArray.size(); + if (nDashArrayCount > 0) + { + pDashPattern = new double[nDashArrayCount]; + if (pDashPattern) + { + lDashPatternSize = nDashArrayCount; + for (int nIndex = 0; nIndex < nDashArrayCount; nIndex++) + { + pDashPattern[nIndex] = GetDouble(arrDashArray.at(nIndex)); + } + } + } + } + else if (L"StrokeDashOffset" == wsAttrName) + { + std::wstring wsDashOffset = oReader.GetText(); + dDashOffset = GetDouble(wsDashOffset); + } + else if (L"StrokeDashCap" == wsAttrName) + { + nDashCap = GetCapStyle(oReader.GetText()); + } + else if (L"StrokeEndLineCap" == wsAttrName) + { + nEndCap = GetCapStyle(oReader.GetText()); + } + else if (L"StrokeStartLineCap" == wsAttrName) + { + nStartCap = GetCapStyle(oReader.GetText()); + } + else if (L"StrokeLineJoin" == wsAttrName) + { + CWString wsJoin = oReader.GetText(); + if (wsJoin == L"Miter") + nJoinStyle = Aggplus::LineJoinMiter; + else if (wsJoin == L"Bevel") + nJoinStyle = Aggplus::LineJoinBevel; + else if (wsJoin == L"Round") + nJoinStyle = Aggplus::LineJoinRound; + } + else if (L"StrokeMiterLimit" == wsAttrName) + { + CWString wsMiterLimit = oReader.GetText(); + dMiter = GetDouble(wsMiterLimit.c_str()); + } else if (L"Fill" == wsAttrName) { bFillSetted = true; @@ -1067,6 +473,30 @@ namespace XPS } oReader.MoveToElement(); + if (pDashPattern) + { + for (LONG lIndex = 0; lIndex < lDashPatternSize; lIndex++) + { + pDashPattern[lIndex] = xpsUnitToMM(pDashPattern[lIndex] * dPenSize); + } + + pRenderer->put_PenDashStyle(Aggplus::DashStyleCustom); + pRenderer->PenDashPattern(pDashPattern, lDashPatternSize); + pRenderer->put_PenDashOffset(dDashOffset); + pRenderer->put_PenLineStartCap(nDashCap); + pRenderer->put_PenLineEndCap(nDashCap); + delete[] pDashPattern; + } + else + { + pRenderer->put_PenDashStyle(Aggplus::DashStyleSolid); + pRenderer->put_PenLineStartCap(nStartCap); + pRenderer->put_PenLineEndCap(nEndCap); + } + + pRenderer->put_PenLineJoin(nJoinStyle); + if (nJoinStyle == Aggplus::LineJoinMiter) + pRenderer->put_PenMiterLimit(xpsUnitToMM(dMiter)); pRenderer->put_PenSize(xpsUnitToMM(dPenSize)); bool bFill = bFillSetted; @@ -1092,26 +522,39 @@ namespace XPS if (L"" == wsData) ReadPathData(oReader, wsData); - if (L'{' == wsData[0]) - { - std::wstring wsValue = pState->GetFigure(wsData); - if (L"" != wsValue) - wsData = wsValue; - else - { - if (bTransform) - ResetTransform(pRenderer, pState); - - return; - } - } - pRenderer->BeginCommand(c_nPathType); pRenderer->PathCommandStart(); bool bWindingFillMode = false; - if (L'{' != wsData[0]) - bWindingFillMode = VmlToRenderer(wsData, pRenderer); + if (L'{' == wsData[0]) + { + const wchar_t* wsValue = NULL; + if (m_pStaticResource) + { + CWString wsKey(((wchar_t*)wsData.c_str() + 16), false, wsData.length() - 17); + wsValue = m_pStaticResource->Get(wsKey); + } + + if (NULL != wsValue) + { + bWindingFillMode = VmlToRenderer(wsValue, pRenderer); + } + else + { + pRenderer->EndCommand(c_nPathType); + pRenderer->PathCommandEnd(); + + if (bClip) + pState->PopClip(); + + if (bTransform) + pState->PopTransform(); + + return; + } + } + else + bWindingFillMode = VmlToRenderer(wsData.c_str(), pRenderer); int nMode = bStroke ? c_nStroke : 0; if (bFill) @@ -1122,31 +565,10 @@ namespace XPS pRenderer->PathCommandEnd(); if (bTransform) - ResetTransform(pRenderer, pState); - } - void Page::FillToRenderer(XmlUtils::CXmlNode& oRootNode, IRenderer* pRenderer) - { - XmlUtils::CXmlNode oBrushNode; - if (oRootNode.GetNode(L"SolidColorBrush", oBrushNode)) - { - int nBgr, nAlpha; - std::wstring wsColor = oBrushNode.GetAttribute(L"Color", L"#00FFFFFF"); - GetBgra(wsColor, nBgr, nAlpha); - pRenderer->put_BrushType(c_BrushTypeSolid); - pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1(nAlpha); - } - else if (oRootNode.GetNode(L"ImageBrush", oBrushNode)) - { - std::wstring wsImageSource = oBrushNode.GetAttribute(L"ImageSource"); - pRenderer->put_BrushType(c_BrushTypeTexture); - pRenderer->put_BrushTexturePath(m_wsRootPath + wsImageSource); - } - else - { - pRenderer->put_BrushAlpha1(0); - pRenderer->put_BrushAlpha2(0); - } + pState->PopTransform(); + + if (bClip) + pState->PopClip(); } bool Page::FillToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer) { @@ -1183,82 +605,6 @@ namespace XPS return false; } - void Page::GetDataFromNode(std::wstring& wsString, XmlUtils::CXmlNode& oNode) - { - wsString = L""; - - XmlUtils::CXmlNode oPathDataNode; - oNode.GetNode(L"Path.Data", oPathDataNode); - - XmlUtils::CXmlNode oGeometryNode; - oPathDataNode.GetNode(_T("PathGeometry"), oGeometryNode); - - std::wstring wsFillMode = oGeometryNode.GetAttribute(L"FillRule", L"EvenOdd"); - if (L"EvenOdd" == wsFillMode) - wsString += L"F 0 "; - else - wsString += L"F 1 "; - - XmlUtils::CXmlNodes arrFigureNodes; - XmlUtils::CXmlNode oFigureNode; - XmlUtils::CXmlNodes arrSegmentNodes; - XmlUtils::CXmlNode oSegmentNode; - oGeometryNode.GetNodes(L"PathFigure", arrFigureNodes); - for (int nFigureIndex = 0, nFiguresCount = arrFigureNodes.GetCount(); nFigureIndex < nFiguresCount; nFigureIndex++) - { - arrFigureNodes.GetAt(nFigureIndex, oFigureNode); - - std::wstring wsStartPoint = oFigureNode.GetAttribute(L"StartPoint"); - wsString += L" M " + wsStartPoint; - - oFigureNode.GetNodes(L"*", arrSegmentNodes); - for (int nSegmentIndex = 0, nSegmentsCount = arrSegmentNodes.GetCount(); nSegmentIndex < nSegmentsCount; nSegmentIndex++) - { - arrSegmentNodes.GetAt(nSegmentIndex, oSegmentNode); - std::wstring wsName = oSegmentNode.GetName(); - if (L"PolyLineSegment" == wsName) - { - wsString += L" L "; - wsString += oSegmentNode.GetAttribute(L"Points"); - } - else if (L"PolyBezierSegment" == wsName) - { - wsString += L" C "; - wsString += oSegmentNode.GetAttribute(L"Points"); - } - else if (L"PolyQuadraticBezierSegment" == wsName) - { - wsString += L" Q "; - wsString += oSegmentNode.GetAttribute(L"Points"); - } - else if (L"ArcSegment" == wsName) - { - wsString += L" A "; - wsString += oSegmentNode.GetAttribute(L"Size"); - wsString += L" "; - wsString += oSegmentNode.GetAttribute(L"RotationAngle"); - wsString += L" "; - - std::wstring wsIsLargeArc = oSegmentNode.GetAttribute(L"IsLargeArc"); - if (GetBool(wsIsLargeArc)) - wsString += L"1 "; - else - wsString += L"0 "; - - std::wstring wsSweepDirection = oSegmentNode.GetAttribute(L"SweepDirection"); - if (L"Counterclockwise" == wsSweepDirection) - wsString += L"0 "; - else - wsString += L"1 "; - wsString += oSegmentNode.GetAttribute(L"Point"); - } - } - - std::wstring wsClosed = oFigureNode.GetAttribute(L"IsClosed"); - if (GetBool(wsClosed)) - wsString += L" Z "; - } - } void Page::ReadPathData(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData) { wsData = L""; diff --git a/XpsFile/XpsLib/Page.h b/XpsFile/XpsLib/Page.h index 655229a9d9..23f159afd8 100644 --- a/XpsFile/XpsLib/Page.h +++ b/XpsFile/XpsLib/Page.h @@ -12,6 +12,7 @@ namespace XPS { class CDocument; + class CStaticResource; class Page { @@ -24,36 +25,30 @@ namespace XPS private: - void DrawCanvas(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak); + void DrawCanvas (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState, bool* pbBreak); void ReadPageResources(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); - void DrawGlyph(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); - void CanvasTransform(XmlUtils::CXmlLiteReader& oRNode, IRenderer* pRenderer, CContextState* pState); - void DrawPath(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); - bool FillToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer); - void ReadPathData(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); - void ReadPathGeometry(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); - void ReadPathFigure(XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); - - void DrawCanvas(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState, bool* pbBreak); - void DrawGlyph(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState); - void DrawPath(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState); - void CanvasTransform(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer, CContextState* pState); - void FillToRenderer(XmlUtils::CXmlNode& oNode, IRenderer* pRenderer); - void GetDataFromNode(std::wstring& wsString, XmlUtils::CXmlNode& oNode); - - bool VmlToRenderer(std::wstring& wsValue, IRenderer* pRenderer); - void TransformToRenderer(const std::wstring& wsString, IRenderer* pRenderer, CContextState* pState); - void ResetTransform(IRenderer* pRenderer, CContextState* pState); - - void PrepareVmlString(std::wstring& wsString); + void DrawGlyph (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); + bool ReadTransform (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); + void DrawPath (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); + bool FillToRenderer (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer); + void ReadPathData (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); + void ReadPathGeometry (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); + void ReadPathFigure (XmlUtils::CXmlLiteReader& oReader, std::wstring& wsData); + + bool ClipToRenderer (const wchar_t* wsString, CContextState* pState); + bool TransformToRenderer(const wchar_t* wsString, CContextState* pState); private: - std::wstring m_wsPagePath; - std::wstring m_wsRootPath; - CFontList* m_pFontList; - CFontManager* m_pFontManager; - CDocument* m_pDocument; + std::wstring m_wsPagePath; + std::wstring m_wsRootPath; + CFontList* m_pFontList; + CFontManager* m_pFontManager; + CDocument* m_pDocument; + CStaticResource* m_pStaticResource; + bool m_bDeleteStaticResource; + + int m_nCounter; }; } diff --git a/XpsFile/XpsLib/Utils.cpp b/XpsFile/XpsLib/Utils.cpp index 986d5a7e51..70b645b160 100644 --- a/XpsFile/XpsLib/Utils.cpp +++ b/XpsFile/XpsLib/Utils.cpp @@ -2,9 +2,445 @@ #include "../../DesktopEditor/common/String.h" #include "../../DesktopEditor/common/Types.h" #include "../../Common/DocxFormat/Source/XML/xmlutils.h" +#include "../../DesktopEditor/graphics/IRenderer.h" + +#define MAX_STRING_LEN 2147483648 + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef xpsUnitToMM +#define xpsUnitToMM(x) ((x) * 25.4 / 96) +#endif + +#define IsNumber(X) \ + ('0' == (X)\ + || '1' == (X)\ + || '2' == (X)\ + || '3' == (X)\ + || '4' == (X)\ + || '5' == (X)\ + || '6' == (X)\ + || '7' == (X)\ + || '8' == (X)\ + || '9' == (X)\ + || '-' == (X)\ + || '.' == (X)) + +#define GetChar(STRING, POS) STRING[POS++] +#define LookChar(STRING, POS) STRING[POS] + +namespace XPS +{ + static inline bool SkipWhiteSpaces(const wchar_t* wsString, int& nPos, const int& nLen) + { + while (1) + { + if (nPos >= nLen) + return false; + wchar_t wChar = LookChar(wsString, nPos); + if (' ' == wChar || ',' == wChar) + { + nPos++; + continue; + } + else + break; + } + + return true; + } + static inline double GetNumber(const wchar_t* wsString, int& nPos, const int& nLen) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + return 0.0; + + wchar_t wChar = GetChar(wsString, nPos); + if (IsNumber(wChar)) + { + bool bNegative = false; + int nInt = 0; + double dFloat = 0.0, dScale = 0.1; + + if ('-' == wChar) + { + bNegative = true; + } + else if ('.' == wChar) + { + goto doReal; + } + else + { + nInt = wChar - '0'; + } + + while (1) + { + wChar = LookChar(wsString, nPos); + if (isdigit(wChar)) + { + nPos++; + nInt = nInt * 10 + (wChar - '0'); + } + else if ('.' == wChar) + { + nPos++; + dFloat = (double)nInt; + goto doReal; + } + else + { + break; + } + } + + return (bNegative ? (double)(-nInt) : (double)nInt); + + doReal: + + while (1) + { + wChar = LookChar(wsString, nPos); + if (!isdigit(wChar)) + break; + + nPos++; + dFloat = dFloat + dScale * (wChar - '0'); + dScale *= 0.1; + } + + return (bNegative ? (double)(-dFloat) : (double)dFloat); + } + + return 0.0; + } + static inline bool GetBool(const wchar_t* wsString, int& nPos, const int& nLen) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + return false; + + int nBufPos = 0; + wchar_t pBuffer[32]; + memset(pBuffer, 0x00, sizeof(wchar_t) * 32); + + wchar_t wChar = LookChar(wsString, nPos); + while (' ' != wChar) + { + pBuffer[nBufPos++] = wChar; + nPos++; + + if (nPos >= nLen) + break; + + wChar = LookChar(wsString, nPos); + } + + CWString wsBool(pBuffer, false, nBufPos); + if ((wsBool == L"true") || (wsBool == L"t") || (wsBool == L"1") || (wsBool == L"on")) + return true; + + return false; + } + static inline void PageCommandA(const wchar_t* wsString, int& nPos, const int& nLen, double& dCurX, double& dCurY, IRenderer* pRenderer) + { + Aggplus::CMatrix tmatx, rmatx, smatx, itmatx, irmatx, ismatx; + double x_cur_temp = dCurX; + double y_cur_temp = dCurY; + + double rx = GetNumber(wsString, nPos, nLen); + double ry = GetNumber(wsString, nPos, nLen); + double angle = GetNumber(wsString, nPos, nLen); + + bool isLarge = GetBool(wsString, nPos, nLen); + bool isCCW = !GetBool(wsString, nPos, nLen); + + double x_end = GetNumber(wsString, nPos, nLen); + double y_end = GetNumber(wsString, nPos, nLen); + + tmatx.Translate(-dCurX, -dCurY); + tmatx.TransformPoint(x_cur_temp, y_cur_temp); + tmatx.TransformPoint(x_end, y_end); + + rmatx.Rotate(-angle); + rmatx.TransformPoint(x_cur_temp, y_cur_temp); + rmatx.TransformPoint(x_end, y_end); + + smatx.Scale(ry / rx, 1); + smatx.TransformPoint(x_cur_temp, y_cur_temp); + smatx.TransformPoint(x_end, y_end); + + double mid_x = (x_cur_temp + x_end) / 2.0, mid_y = (y_cur_temp + y_end) / 2.0; + double vect_x = x_end - x_cur_temp, vect_y = y_end - y_cur_temp; + double length = sqrt(vect_x * vect_x + vect_y * vect_y); + double halfChord = length / 2.0; + double rotated_x, rotated_y; + + if (isLarge == isCCW) + { + rotated_x = -vect_y; + rotated_y = vect_x; + } + else + { + rotated_x = vect_y; + rotated_y = -vect_x; + } + + rotated_x = rotated_x / length; + rotated_y = rotated_y / length; + + double centerDistance = sqrt(max(ry * ry - halfChord * halfChord, 0)); + double center_x = mid_x + centerDistance * rotated_x, center_y = mid_y + centerDistance * rotated_y; + + double angle1 = atan2(y_cur_temp - center_y, x_cur_temp - center_x); + double angle2 = atan2(y_end - center_y, x_end - center_x); + + if ((!isCCW) && (abs(y_end - center_y) < 0.000001) && (x_end - center_x < 0)) + angle2 = -M_PI; + if ((isCCW) && (abs(y_cur_temp - center_y) < 0.000001) && (x_cur_temp - center_x < 0)) + angle1 = -M_PI; + + if (isLarge == (abs(angle2 - angle1) < M_PI)) + { + if (angle1 < angle2) + angle1 += 2 * M_PI; + else + angle2 += 2 * M_PI; + } + if (abs(angle2 - angle1) == M_PI) + { + if ((angle1 < angle2) && (isCCW) && (angle1 != -M_PI) && (angle1 != 0.0) && (angle1 != M_PI)) + angle1 += 2 * M_PI; + } + + itmatx.Translate(dCurX, dCurY); + irmatx.Rotate(angle); + ismatx.Scale(rx / ry, 1); + + int max = (int)((4 * (rx + ry) * abs(angle2 - angle1) / (2 * M_PI)) / 1/*tolerance*/); + + double x, y; + for (int counter = 0; counter <= max; counter++) + { + double angle_cur = ((max - counter) * angle1 + counter * angle2) / max; + x = center_x + ry * cos(angle_cur); + y = center_y + ry * sin(angle_cur); + + // Transform the point back + ismatx.TransformPoint(x, y); + irmatx.TransformPoint(x, y); + itmatx.TransformPoint(x, y); + pRenderer->PathCommandLineTo(xpsUnitToMM(x), xpsUnitToMM(y)); + } + + dCurX = x; + dCurY = y; + } +} namespace XPS { + class CWStringBuffer + { + public: + + CWStringBuffer(const wchar_t* wsString, unsigned int unLen) + { + if (unLen) + { + m_pBuffer = new wchar_t[unLen + 1]; + m_pBuffer[unLen] = 0x00; + memcpy(m_pBuffer, wsString, sizeof(wchar_t) * unLen); + } + else + { + m_pBuffer = NULL; + } + + m_nRefCount = 1; + } + void AddRef() + { + m_nRefCount++; + } + int Release() + { + return --m_nRefCount; + } + void Free() + { + RELEASEARRAYOBJECTS(m_pBuffer); + } + wchar_t operator[](const unsigned int& unIndex) const + { + return m_pBuffer[unIndex]; + } + + private: + + wchar_t* m_pBuffer; + int m_nRefCount; + + friend class CWString; + }; + CWString::CWString() + { + m_bOwnBuffer = false; + m_pBuffer = NULL; + m_unLen = 0; + } + CWString::CWString(const wchar_t* wsString) + { + m_bOwnBuffer = false; + m_pBuffer = NULL; + m_unLen = 0; + create(wsString, false); + } + CWString::CWString(wchar_t* wsString, bool bCopy, int nLen) + { + m_bOwnBuffer = false; + m_pBuffer = NULL; + m_unLen = 0; + create(wsString, bCopy, nLen); + } + CWString::CWString(const CWString& wsString) + { + m_unLen = wsString.m_unLen; + m_bOwnBuffer = wsString.m_bOwnBuffer; + m_pBuffer = wsString.m_pBuffer; + if (m_bOwnBuffer && m_pBuffer) + ((CWStringBuffer*)m_pBuffer)->AddRef(); + } + CWString::~CWString() + { + clear(); + } + void CWString::create(const wchar_t* wsString, bool bCopy, int nLen) + { + clear(); + unsigned int unLen = -1 == nLen ? min(wcslen(wsString), MAX_STRING_LEN) : (unsigned int)nLen; + m_unLen = unLen; + if (bCopy) + { + if (unLen) + { + m_pBuffer = (void*)(new CWStringBuffer(wsString, m_unLen)); + m_bOwnBuffer = true; + } + } + else + { + m_pBuffer = (void*)wsString; + m_bOwnBuffer = false; + } + } + void CWString::clear() + { + if (m_bOwnBuffer) + { + CWStringBuffer* pWStringBuffer = (CWStringBuffer*)m_pBuffer; + if (pWStringBuffer && !pWStringBuffer->Release()) + delete pWStringBuffer; + } + + m_bOwnBuffer = false; + m_pBuffer = NULL; + m_unLen = 0; + } + void CWString::operator=(const wchar_t* wsString) + { + clear(); + create(wsString, false); + } + void CWString::operator=(const CWString& wsString) + { + clear(); + m_unLen = wsString.m_unLen; + m_bOwnBuffer = wsString.m_bOwnBuffer; + m_pBuffer = wsString.m_pBuffer; + if (m_bOwnBuffer && m_pBuffer) + ((CWStringBuffer*)m_pBuffer)->AddRef(); + } + const wchar_t* CWString::c_str() const + { + if (m_bOwnBuffer) + { + CWStringBuffer* pWStringBuffer = (CWStringBuffer*)m_pBuffer; + if (pWStringBuffer) + return pWStringBuffer->m_pBuffer; + + return NULL; + } + + return (const wchar_t*)m_pBuffer; + } + bool CWString::operator<(const CWString& wsString) const + { + const wchar_t* wsLeft = this->c_str(); + const wchar_t* wsRight = wsString.c_str(); + + unsigned int unLen = min(m_unLen, wsString.m_unLen); + for (unsigned int unPos = 0; unPos < unLen; unPos++) + { + if (wsLeft[unPos] < wsRight[unPos]) + return true; + else if (wsLeft[unPos] > wsRight[unPos]) + return false; + } + + return (m_unLen > wsString.m_unLen); + } + bool CWString::operator>(const CWString& wsString) const + { + return !operator<(wsString); + } + bool CWString::operator==(const CWString& wsString) const + { + const wchar_t* wsLeft = this->c_str(); + const wchar_t* wsRight = wsString.c_str(); + + if (m_unLen != wsString.m_unLen) + return false; + + for (unsigned int unPos = 0; unPos < m_unLen; unPos++) + { + if (wsLeft[unPos] != wsRight[unPos]) + return false; + } + + return true; + } + bool CWString::operator==(const wchar_t* wsString) const + { + const wchar_t* wsLeft = this->c_str(); + unsigned unLen = min(wcslen(wsString), MAX_STRING_LEN); + + if (m_unLen != unLen) + return false; + + for (unsigned int unPos = 0; unPos < m_unLen; unPos++) + { + if (wsLeft[unPos] != wsString[unPos]) + return false; + } + + return true; + } + unsigned int CWString::size() const + { + return m_unLen; + } + wchar_t CWString::operator[](const unsigned int& unIndex) const + { + return this->c_str()[unIndex]; + } + bool CWString::empty() const + { + return 0 == m_unLen; + } + int GetDigit(wchar_t wChar) { if (wChar >= '0' && wChar <= '9') @@ -31,7 +467,7 @@ namespace XPS bool GetBool(const std::wstring& wsString) { std::wstring wsStr = wsString; - NSString::ToLower(wsStr); + NSStringExt::ToLower(wsStr); if ((wsStr == L"true") || (wsStr == L"t") || (wsStr == L"1") || (wsStr == L"on")) return true; @@ -68,7 +504,7 @@ namespace XPS else if (L's' == wsString[0] && L'c' == wsString[1] && L'#' == wsString[2]) { std::wstring wsStr = wsString.substr(3); - std::vector arrElements = NSString::Split(wsStr, L','); + std::vector arrElements = NSStringExt::Split(wsStr, L','); if (3 == arrElements.size()) { @@ -84,13 +520,28 @@ namespace XPS else return; } + unsigned char GetCapStyle(const wchar_t* wsCapStyle) + { + BYTE nCapStyle = Aggplus::LineCapFlat; + CWString wsDashCap = wsCapStyle; + if (wsDashCap == L"Flat") + nCapStyle = Aggplus::LineCapFlat; + else if (wsDashCap == L"Round") + nCapStyle = Aggplus::LineCapRound; + else if (wsDashCap == L"Square") + nCapStyle = Aggplus::LineCapSquare; + else if (wsDashCap == L"Triangle") + nCapStyle = Aggplus::LineCapTriangle; + + return nCapStyle; + } std::wstring NormalizePath(const std::wstring& wsPath) { std::wstring wsResult = wsPath; - NSString::Replace(wsResult, L"/", L"\\"); + NSStringExt::Replace(wsResult, L"/", L"\\"); while (std::wstring::npos != wsResult.find(L"\\\\")) { - NSString::Replace(wsResult, L"\\\\", L"\\"); + NSStringExt::Replace(wsResult, L"\\\\", L"\\"); } return wsResult; } @@ -141,11 +592,11 @@ namespace XPS std::vector> Split(const std::wstring& wsString, wchar_t wDelim1, wchar_t wDelim2) { std::vector> arrResult; - std::vector arrStrings = NSString::Split(wsString, wDelim1); + std::vector arrStrings = NSStringExt::Split(wsString, wDelim1); int nCount = arrStrings.size(); for (int nIndex = 0; nIndex < nCount; nIndex++) { - std::vector arrStr = NSString::Split(arrStrings[nIndex], wDelim2); + std::vector arrStr = NSStringExt::Split(arrStrings[nIndex], wDelim2); arrResult.push_back(arrStr); } return arrResult; @@ -175,4 +626,255 @@ namespace XPS oReader.MoveToElement(); } + bool VmlToRenderer(const wchar_t* wsString, IRenderer* pRenderer) + { + bool bWinding = false; + + int nPos = 0; + int nLen = wcslen(wsString); + + double dCurX = 0.0, dCurY = 0.0; + double dCpX = 0.0, dCpY = 0.0; + + bool bPrevCommandIsCurve = false; + wchar_t wChar = 0x00; + while (nPos < nLen) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + wChar = GetChar(wsString, nPos); + switch (wChar) + { + case 'F': + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + bWinding = GetBool(wsString, nPos, nLen); + bPrevCommandIsCurve = false; + break; + } + case 'm': + { + dCurX += GetNumber(wsString, nPos, nLen); + dCurY += GetNumber(wsString, nPos, nLen); + pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + bPrevCommandIsCurve = false; + break; + } + case 'M': + { + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + pRenderer->PathCommandMoveTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + bPrevCommandIsCurve = false; + break; + } + case 'L': + case 'l': + case 'H': + case 'h': + case 'V': + case 'v': + { + while (true) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + if (IsNumber(LookChar(wsString, nPos))) + { + switch (wChar) + { + case 'L': + { + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + break; + } + case 'l': + { + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + break; + } + case 'H': + { + dCurX = GetNumber(wsString, nPos, nLen); + break; + } + case 'h': + { + dCurX += GetNumber(wsString, nPos, nLen); + break; + } + case 'V': + { + dCurY = GetNumber(wsString, nPos, nLen); + break; + } + case 'v': + { + dCurY += GetNumber(wsString, nPos, nLen); + break; + } + } + + pRenderer->PathCommandLineTo(xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + } + else + break; + } + + bPrevCommandIsCurve = false; + break; + } + case 'A': + case 'a': + { + while (true) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + if (IsNumber(LookChar(wsString, nPos))) + PageCommandA(wsString, nPos, nLen, dCurX, dCurY, pRenderer); + else + break; + } + bPrevCommandIsCurve = false; + break; + } + case 'C': + case 'c': + { + while (true) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + if (IsNumber(LookChar(wsString, nPos))) + { + double dX1, dY1, dX2, dY2; + if ('c' == wChar) + { + dX1 = dCurX + GetNumber(wsString, nPos, nLen); + dY1 = dCurY + GetNumber(wsString, nPos, nLen); + dX2 = dCurX + GetNumber(wsString, nPos, nLen); + dY2 = dCurY + GetNumber(wsString, nPos, nLen); + dCurX += GetNumber(wsString, nPos, nLen); + dCurY += GetNumber(wsString, nPos, nLen); + } + else + { + dX1 = GetNumber(wsString, nPos, nLen); + dY1 = GetNumber(wsString, nPos, nLen); + dX2 = GetNumber(wsString, nPos, nLen); + dY2 = GetNumber(wsString, nPos, nLen); + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + } + pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX2), xpsUnitToMM(dY2), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + dCpX = dX2; + dCpY = dY2; + bPrevCommandIsCurve = true; + } + else + break; + } + break; + } + case 'Q': + case 'q': + { + while (true) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + if (IsNumber(LookChar(wsString, nPos))) + { + double dX1, dY1; + if ('q' == wChar) + { + dX1 = dCurX + GetNumber(wsString, nPos, nLen); + dY1 = dCurY + GetNumber(wsString, nPos, nLen); + dCurX += GetNumber(wsString, nPos, nLen); + dCurY += GetNumber(wsString, nPos, nLen); + } + else + { + dX1 = GetNumber(wsString, nPos, nLen); + dY1 = GetNumber(wsString, nPos, nLen); + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + } + pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + } + else + break; + } + bPrevCommandIsCurve = false; + break; + } + case 'S': + case 's': + { + while (true) + { + if (!SkipWhiteSpaces(wsString, nPos, nLen)) + break; + + if (IsNumber(LookChar(wsString, nPos))) + { + double dX1, dY1, dX2, dY2; + if (!bPrevCommandIsCurve) + { + dX1 = dCurX; + dY1 = dCurY; + } + else + { + dX1 = 2 * dCurX - dCpX; + dY1 = 2 * dCurY - dCpY; + } + + if ('s' == wChar) + { + dX2 = dCurX + GetNumber(wsString, nPos, nLen); + dY2 = dCurX + GetNumber(wsString, nPos, nLen); + dCurX += GetNumber(wsString, nPos, nLen); + dCurY += GetNumber(wsString, nPos, nLen); + } + else + { + dX2 = GetNumber(wsString, nPos, nLen); + dY2 = GetNumber(wsString, nPos, nLen); + dCurX = GetNumber(wsString, nPos, nLen); + dCurY = GetNumber(wsString, nPos, nLen); + } + + pRenderer->PathCommandCurveTo(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX2), xpsUnitToMM(dY2), xpsUnitToMM(dCurX), xpsUnitToMM(dCurY)); + dCpX = dX2; + dCpY = dY2; + bPrevCommandIsCurve = true; + } + else + break; + } + break; + } + case 'Z': + case 'z': + { + pRenderer->PathCommandClose(); + bPrevCommandIsCurve = false; + break; + } + } + } + + return bWinding; + } } \ No newline at end of file diff --git a/XpsFile/XpsLib/Utils.h b/XpsFile/XpsLib/Utils.h index ebc5de2a7e..18a7ee31ea 100644 --- a/XpsFile/XpsLib/Utils.h +++ b/XpsFile/XpsLib/Utils.h @@ -9,14 +9,48 @@ namespace XmlUtils class CXmlLiteReader; } +class IRenderer; + namespace XPS { + class CWStringBuffer; + class CWString + { + public: + CWString(); + CWString(const wchar_t* wsString); + CWString(const CWString& wsString); + CWString(wchar_t* wsString, bool bCopy, int nLen = -1); + ~CWString(); + void create(const wchar_t*, bool bCopy, int nLen = -1); + void operator=(const wchar_t* wsString); + void operator=(const CWString& wsString); + bool operator<(const CWString& wsString) const; + bool operator>(const CWString& wsString) const; + bool operator==(const CWString& wsString) const; + bool operator==(const wchar_t* wsString) const; + unsigned int size() const; + bool empty() const; + wchar_t operator[](const unsigned int& unIndex) const; + const wchar_t* c_str() const; + void clear(); + + private: + + void* m_pBuffer; + unsigned int m_unLen; + bool m_bOwnBuffer; + }; + + bool IsAlpha(wchar_t wChar); double GetDouble(const std::wstring& wsString); int GetInteger(const std::wstring& wsString); bool GetBool(const std::wstring& wsString); void GetBgra(const std::wstring& wsString, int& nBgr, int& nAlpha); + unsigned char GetCapStyle(const wchar_t* wsCapStyle); + std::wstring NormalizePath(const std::wstring& wsPath); std::wstring GetPath(const std::wstring& wsPath); std::wstring GetFileName(const std::wstring& wsPath); @@ -26,6 +60,7 @@ namespace XPS std::vector> Split(const std::wstring& wsString, wchar_t wDelim1, wchar_t wDelim2); void ReadAttribute(XmlUtils::CXmlLiteReader& oReader, const wchar_t* wsAttrName, std::wstring& wsAttr); + bool VmlToRenderer(const wchar_t* wsString, IRenderer* pRenderer); } #endif // _XPS_XPSLIB_UTILS_H \ No newline at end of file