diff --git a/XpsFile/XpsLib/ContextState.cpp b/XpsFile/XpsLib/ContextState.cpp index 19dd157018..e84cc221d4 100644 --- a/XpsFile/XpsLib/ContextState.cpp +++ b/XpsFile/XpsLib/ContextState.cpp @@ -21,12 +21,12 @@ namespace XPS while (m_vResourcesStack.size()) PopResource(); } - void CContextState::PushOpacity(const double& dOpacity) + void CContextState::PushOpacity(const double& dOpacity) { m_dCurOpacity *= dOpacity; m_vOpacity.push_back(m_dCurOpacity); } - void CContextState::PopOpacity() + void CContextState::PopOpacity() { m_vOpacity.pop_back(); if (m_vOpacity.size()) @@ -34,24 +34,24 @@ namespace XPS else m_dCurOpacity = 1; } - double CContextState::GetCurrentOpacity() + double CContextState::GetCurrentOpacity() { return m_dCurOpacity; } - void CContextState::PushTransform(const double arrTransform[6]) + 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() + void CContextState::PopTransform() { m_lTransformStack.pop_back(); m_oCurrentTransform = m_lTransformStack.back(); SetTransformToRenderer(); } - double CContextState::NormalizeTransform() + double CContextState::NormalizeTransform() { agg::trans_affine& oMatrix = m_oCurrentTransform.m_agg_mtx; double dDet = sqrt(oMatrix.sx * oMatrix.sy - oMatrix.shx * oMatrix.shy); @@ -65,12 +65,12 @@ namespace XPS return dDet; } - void CContextState::PushClip(const CWString& wsClip) + void CContextState::PushClip(const CWString& wsClip) { m_vClipStack.push_back(wsClip); SetClipToRenderer(wsClip); } - void CContextState::PopClip() + void CContextState::PopClip() { m_vClipStack.pop_back(); if (m_pRenderer) @@ -85,7 +85,7 @@ namespace XPS } } } - void CContextState::SetTransformToRenderer() + void CContextState::SetTransformToRenderer() { if (m_pRenderer) { @@ -94,7 +94,7 @@ namespace XPS xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.tx), xpsUnitToMM(m_oCurrentTransform.m_agg_mtx.ty)); } } - void CContextState::SetClipToRenderer(const CWString& wsClip) + void CContextState::SetClipToRenderer(const CWString& wsClip) { if (!wsClip.empty() && m_pRenderer) { @@ -108,11 +108,11 @@ namespace XPS m_pRenderer->PathCommandEnd(); } } - void CContextState::PushResource(CStaticResource* pResource, bool bOwn) + void CContextState::PushResource(CStaticResource* pResource, bool bOwn) { m_vResourcesStack.push_back(TStaticRecource(pResource, bOwn)); } - void CContextState::PopResource() + void CContextState::PopResource() { if (m_vResourcesStack.size()) { @@ -123,7 +123,7 @@ namespace XPS m_vResourcesStack.pop_back(); } } - void CContextState::GetPathGeometry(const CWString& _wsKey, CWString& wsPathData, CWString& wsPathTransform) + void CContextState::GetPathGeometry(const CWString& _wsKey, CWString& wsPathData, CWString& wsPathTransform) { if (_wsKey.size() < 17) return; @@ -135,7 +135,7 @@ namespace XPS for (int nIndex = m_vResourcesStack.size() - 1; nIndex >= 0; nIndex--) { pResource = m_vResourcesStack.at(nIndex).pResource; - wsPath = pResource->Get(wsKey); + wsPath = pResource->GetFigure(wsKey); if (NULL != wsPath) { wsPathData.create(wsPath, true); @@ -143,4 +143,23 @@ namespace XPS } } } + CBrush* CContextState::GetBrush(const CWString& _wsKey) + { + if (_wsKey.size() < 17) + return NULL; + + CWString wsKey((wchar_t*)(_wsKey.c_str() + 16), false, _wsKey.size() - 17); + CBrush* pBrush = NULL; + CStaticResource* pResource; + + for (int nIndex = m_vResourcesStack.size() - 1; nIndex >= 0; nIndex--) + { + pResource = m_vResourcesStack.at(nIndex).pResource; + pBrush = pResource->GetBrush(wsKey); + if (pBrush) + return pBrush; + } + + return NULL; + } } \ No newline at end of file diff --git a/XpsFile/XpsLib/ContextState.h b/XpsFile/XpsLib/ContextState.h index 26f43842f2..abc50a7740 100644 --- a/XpsFile/XpsLib/ContextState.h +++ b/XpsFile/XpsLib/ContextState.h @@ -11,6 +11,7 @@ namespace XPS { + class CBrush; class CStaticResource; class CContextState @@ -34,18 +35,23 @@ namespace XPS CContextState(IRenderer* pRenderer); ~CContextState(); - void PushOpacity(const double& dOpacity); - void PopOpacity(); - double GetCurrentOpacity(); - void PushClip(const CWString& wsClip); - void PopClip(); - void PushTransform(const double arrTransform[6]); - void PopTransform(); - double NormalizeTransform(); - void PushResource(CStaticResource* pResource, bool bOwn); - void PopResource(); - - void GetPathGeometry(const CWString& wsKey, CWString& wsPathData, CWString& wsPathTransform); + void PushOpacity(const double& dOpacity); + void PopOpacity(); + double GetCurrentOpacity(); + void PushClip(const CWString& wsClip); + void PopClip(); + void PushTransform(const double arrTransform[6]); + void PopTransform(); + double NormalizeTransform(); + void PushResource(CStaticResource* pResource, bool bOwn); + void PopResource(); + + void GetPathGeometry(const CWString& wsKey, CWString& wsPathData, CWString& wsPathTransform); + CBrush* GetBrush(const CWString& wsKey); + Aggplus::CMatrix GetCurrentTransform() + { + return m_oCurrentTransform; + } private: diff --git a/XpsFile/XpsLib/Document.cpp b/XpsFile/XpsLib/Document.cpp index 481049b538..e2c33bf3a4 100644 --- a/XpsFile/XpsLib/Document.cpp +++ b/XpsFile/XpsLib/Document.cpp @@ -132,99 +132,7 @@ namespace XPS } - return true; - - //Close(); - - //m_wsPath = wsPath; - - //XmlUtils::CXmlNode oNode; - //XmlUtils::CXmlNodes arrNodes; - //XmlUtils::CXmlNode oSubnode; - // - //std::wstring wsRelsPath = NormalizePath(wsPath + L"_rels/.rels"); - - //clock_t oBeginTime = clock(); - - //if (!oNode.FromXmlFile(wsRelsPath.c_str())) - // return false; - - //clock_t oEndTime = clock(); - //double dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - //printf("%S %fseconds\n", wsRelsPath.c_str(), dElapsedSecs); - - //// Checking root node - //if (L"Relationships" != oNode.GetName()) - // return false; - - //if (!oNode.GetNodes(L"Relationship", arrNodes)) - // return false; - - //std::wstring wsFile; - //for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++) - //{ - // arrNodes.GetAt(nIndex, oNode); - - // if (L"http://schemas.microsoft.com/xps/2005/06/fixedrepresentation" == oNode.GetAttribute(L"Type")) - // { - // wsFile = oNode.GetAttribute(L"Target"); - // break; - // } - - // if (nIndex == nCount - 1) - // return false; - //} - - //oBeginTime = clock(); - - //if (!oNode.FromXmlFile((wsPath + wsFile).c_str())) - // return false; - - //oEndTime = clock(); - //dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - //printf("%S %fseconds\n", (wsPath + wsFile).c_str(), dElapsedSecs); - - //// Checking root node - //if (L"FixedDocumentSequence" != oNode.GetName()) - // return false; - - //if (!oNode.GetNode(L"DocumentReference", oSubnode)) - // return false; - - //wsFile = oSubnode.GetAttribute(L"Source"); - - //oBeginTime = clock(); - - //if (!oNode.FromXmlFile((m_wsPath + wsFile).c_str())) - // return false; - - //oEndTime = clock(); - //dElapsedSecs = double(oEndTime - oBeginTime) / CLOCKS_PER_SEC; - //printf("%S %fseconds\n", (m_wsPath + wsFile).c_str(), dElapsedSecs); - - //if (L"FixedDocument" != oNode.GetName()) - // return false; - - //if (!oNode.GetNodes(L"PageContent", arrNodes)) - // return false; - - //std::wstring wsFilePath = GetPath(m_wsPath + wsFile); - //std::wstring wsPagePath; - //std::wstring wsSource; - - //for (int nIndex = 0, nCount = arrNodes.GetCount(); nIndex < nCount; nIndex++) - //{ - // arrNodes.GetAt(nIndex, oNode); - // wsSource = oNode.GetAttribute(L"Source"); - // if('/' == wsSource[0]) - // wsPagePath = m_wsPath + wsSource; - // else - // wsPagePath = wsFilePath + wsSource; - - // m_mPages.insert(std::pair(nIndex, new XPS::Page(wsPagePath, wsPath, &m_oFontList, m_pFontManager))); - //} - - //return true; + return true; } int CDocument::GetPageCount()const { diff --git a/XpsFile/XpsLib/Page.cpp b/XpsFile/XpsLib/Page.cpp index 2f82bd4fa1..4e253506ab 100644 --- a/XpsFile/XpsLib/Page.cpp +++ b/XpsFile/XpsLib/Page.cpp @@ -2,10 +2,13 @@ #include #include "../../DesktopEditor/common/String.h" #include "../../DesktopEditor/graphics/structures.h" +#include "../../PdfWriter/PdfRenderer.h" #include "Document.h" #include "StaticResources.h" +#include + #include #ifndef M_PI @@ -20,21 +23,32 @@ namespace XPS { - static double GetAdvance(CFontManager* pFontManager, const std::wstring& wsChar, const std::wstring& wsGid, const bool& bGid) + static double GetAdvanceX(CFontManager* pFontManager, const unsigned int& unUnicode, const unsigned int& unGid, const bool& bGid) { if (bGid) { pFontManager->SetStringGID(TRUE); - pFontManager->LoadString1(wsGid, 0, 0); + return pFontManager->MeasureChar(unGid).fAdvanceX; } else { pFontManager->SetStringGID(FALSE); - pFontManager->LoadString1(wsChar, 0, 0); + return pFontManager->MeasureChar(unUnicode).fAdvanceX; } - TBBox oBox = pFontManager->MeasureString2(); - return (oBox.fMaxX - oBox.fMinX); } + static double GetAdvanceY(CFontManager* pFontManager, const unsigned int& unUnicode, const unsigned int& unGid, const bool& bGid) + { + if (bGid) + { + pFontManager->SetStringGID(TRUE); + return pFontManager->MeasureChar(unGid).fAdvanceY; + } + else + { + pFontManager->SetStringGID(FALSE); + return pFontManager->MeasureChar(unUnicode).fAdvanceY; + } + } Page::Page(const std::wstring& wsPagePath, const std::wstring& wsRootPath, CFontList* pFontList, CFontManager* pFontManager, CDocument* pDocument) { m_wsPagePath = wsPagePath; @@ -364,7 +378,6 @@ namespace XPS } void Page::DrawGlyph(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { - int nBgr = 0, nAlpha = 255; double dFontSize = 10.0; bool bTransform = false, bClip = false, bOpacity = false; double dX = 0; @@ -377,6 +390,8 @@ namespace XPS unsigned short* pUtf16Ptr = NULL; unsigned int unUtf16Len = 0; CWString wsIndices; + CWString wsFill; + bool bIsSideways = false; if (oReader.MoveToFirstAttribute()) { @@ -400,7 +415,9 @@ namespace XPS } else if (wsAttrName == L"Opacity") { - pState->PushOpacity(GetDouble(oReader.GetText())); + double dOpacity; + ReadSTDouble(oReader.GetText(), dOpacity); + pState->PushOpacity(dOpacity); bOpacity = true; } else if (L"Clip" == wsAttrName) @@ -409,9 +426,7 @@ namespace XPS } else if (L"Fill" == wsAttrName) { - std::wstring wsFontColor = oReader.GetText(); - ReadAttribute(oReader, L"Fill", wsFontColor); - GetBgra(wsFontColor, nBgr, nAlpha); + wsFill.create(oReader.GetText(), true); } else if (L"StyleSimulations" == wsAttrName) { @@ -469,6 +484,10 @@ namespace XPS { nBidiLevel = GetInteger(oReader.GetText()); } + else if (wsAttrName == L"IsSideways") + { + bIsSideways = GetBool(oReader.GetText()); + } if (!oReader.MoveToNextAttribute()) break; @@ -494,6 +513,41 @@ namespace XPS } } + CBrush* pBrush = NULL; + bool bDeleteBrush = false; + if (!wsFill.empty()) + { + if (IsFromResource(wsFill)) + { + pBrush = pState->GetBrush(wsFill); + bDeleteBrush = false; + } + else + { + pBrush = ReadBrush(wsFill.c_str(), pState->GetCurrentOpacity()); + bDeleteBrush = true; + } + } + + if (!pBrush || !pBrush->SetToRenderer(pRenderer)) + { + if (bDeleteBrush) + RELEASEOBJECT(pBrush); + + RELEASEARRAYOBJECTS(pUtf16Ptr); + + if (bClip) + pState->PopClip(); + + if (bTransform) + pState->PopTransform(); + + if (bOpacity) + pState->PopOpacity(); + + return; + } + // Сначала задается матрица преобразования, потом клип, потому что даже // если преобразование задано в дочерней ноде, а клип задан в атрибутах данной ноды, // то преобразование влияется на клип все равно. @@ -512,9 +566,6 @@ namespace XPS bClip = ClipToRenderer(wsClip.c_str(), pState); } - pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1(((double)nAlpha * pState->GetCurrentOpacity())); - pRenderer->put_BrushType(c_BrushTypeSolid); pRenderer->put_FontSize(dFontSize * 0.75); TIndicesEntry oEntry; @@ -524,41 +575,72 @@ namespace XPS m_pFontManager->LoadFontFromFile(wsFontPath, 0, (float)(dFontSize * 0.75), 96, 96); double dFontKoef = dFontSize / 100.0; - while (GetNextGlyph(wsIndices.c_str(), nIndicesPos, nIndicesLen, pUtf16, nUtf16Pos, unUtf16Len, oEntry)) + if (!bIsSideways) { - std::wstring wsChar = NSStringExt::CConverter::GetUnicodeFromUTF32((const unsigned int*)(&(oEntry.nUnicode)), 1); - unsigned int unGid = oEntry.nGid; - std::wstring wsGid = oEntry.bGid ? NSStringExt::CConverter::GetUnicodeFromUTF32((const unsigned int*)(&(unGid)), 1) : L""; - - double dAdvance, dRealAdvance; - if (oEntry.bAdvance) + while (GetNextGlyph(wsIndices.c_str(), nIndicesPos, nIndicesLen, pUtf16, nUtf16Pos, unUtf16Len, oEntry)) { - dAdvance = oEntry.dAdvance * dFontKoef; + double dAdvance, dRealAdvance; + if (oEntry.bAdvance) + { + dAdvance = oEntry.dAdvance * dFontKoef; + + if (bRtoL) + dRealAdvance = GetAdvanceX(m_pFontManager, oEntry.nUnicode, oEntry.nGid, oEntry.bGid); + else + dRealAdvance = dAdvance; + } + else + { + dAdvance = GetAdvanceX(m_pFontManager, oEntry.nUnicode, oEntry.nGid, oEntry.bGid); + dRealAdvance = dAdvance; + } if (bRtoL) - dRealAdvance = GetAdvance(m_pFontManager, wsChar, wsGid, oEntry.bGid); + dX -= dRealAdvance; + + double dXorigin = (oEntry.bHorOffset || oEntry.bVerOffset) ? dX + (bRtoL ? -oEntry.dHorOffset * dFontKoef : oEntry.dHorOffset * dFontKoef) : dX; + double dYorigin = (oEntry.bHorOffset || oEntry.bVerOffset) ? dY - oEntry.dVerOffset * dFontKoef : dY; + if (oEntry.bGid) + pRenderer->CommandDrawTextExCHAR(oEntry.nUnicode, oEntry.nGid, xpsUnitToMM(dXorigin), xpsUnitToMM(dYorigin), 0, 0, 0, 0); else - dRealAdvance = dAdvance; + pRenderer->CommandDrawTextCHAR(oEntry.nUnicode, xpsUnitToMM(dXorigin), xpsUnitToMM(dYorigin), 0, 0, 0); + + if (!bRtoL) + dX += dAdvance; + else + dX -= (dAdvance - dRealAdvance); } - else - { - dAdvance = GetAdvance(m_pFontManager, wsChar, wsGid, oEntry.bGid); - dRealAdvance = dAdvance; - } - - if (bRtoL) - dX -= dRealAdvance; - - if (oEntry.bHorOffset || oEntry.bVerOffset) - pRenderer->CommandDrawTextEx(wsChar, wsGid, xpsUnitToMM(dX + (bRtoL ? -oEntry.dHorOffset * dFontKoef : oEntry.dHorOffset * dFontKoef)), xpsUnitToMM(dY - oEntry.dVerOffset * dFontKoef), 0, 0, 0, 0); - else - pRenderer->CommandDrawTextEx(wsChar, wsGid, xpsUnitToMM(dX), xpsUnitToMM(dY), 0, 0, 0, 0); - - if (!bRtoL) - dX += dAdvance; - else - dX -= (dAdvance - dRealAdvance); } + else + { + while (GetNextGlyph(wsIndices.c_str(), nIndicesPos, nIndicesLen, pUtf16, nUtf16Pos, unUtf16Len, oEntry)) + { + double dAdvanceX = GetAdvanceX(m_pFontManager, oEntry.nUnicode, oEntry.nGid, oEntry.bGid); + double dAdvanceY = GetAdvanceY(m_pFontManager, oEntry.nUnicode, oEntry.nGid, oEntry.bGid); + + double dAdvance; + if (oEntry.bAdvance) + dAdvance = oEntry.dAdvance * dFontKoef; + else + dAdvance = dAdvanceY; + + double dXorigin = (oEntry.bHorOffset || oEntry.bVerOffset) ? dX + oEntry.dHorOffset * dFontKoef : dX; + double dYorigin = (oEntry.bHorOffset || oEntry.bVerOffset) ? dY - oEntry.dVerOffset * dFontKoef : dY; + double pTransform[] ={ 0, -1, 1, 0, dXorigin + dAdvanceY, dYorigin + dAdvanceX / 2 }; + pState->PushTransform(pTransform); + + if (oEntry.bGid) + pRenderer->CommandDrawTextExCHAR(oEntry.nUnicode, oEntry.nGid, 0, 0, 0, 0, 0, 0); + else + pRenderer->CommandDrawTextCHAR(oEntry.nUnicode, 0, 0, 0, 0, 0); + + pState->PopTransform(); + dX += dAdvance; + } + } + + if (bDeleteBrush) + RELEASEOBJECT(pBrush); RELEASEARRAYOBJECTS(pUtf16Ptr); @@ -597,6 +679,7 @@ namespace XPS double* pDashPattern = NULL; LONG lDashPatternSize = 0; double dDashOffset = 0.0; + CWString wsFill; CWString wsClip, wsTransform, wsPathData, wsPathTransform; if (oReader.MoveToFirstAttribute()) @@ -614,7 +697,9 @@ namespace XPS } else if (L"Opacity" == wsAttrName) { - pState->PushOpacity(GetDouble(oReader.GetText())); + double dOpacity; + ReadSTDouble(oReader.GetText(), dOpacity); + pState->PushOpacity(dOpacity); bOpacity = true; } else if (L"Stroke" == wsAttrName) @@ -680,9 +765,7 @@ namespace XPS } else if (L"Fill" == wsAttrName) { - bFill = true; - std::wstring wsFill = oReader.GetText(); - GetBgra(wsFill, nFillBgr, nFillAlpha); + wsFill.create(oReader.GetText(), true); } else if (L"Data" == wsAttrName) { @@ -697,19 +780,28 @@ namespace XPS } oReader.MoveToElement(); + CBrush* pBrush = NULL; + bool bDeleteBrush = false; + if (!wsFill.empty()) + { + if (IsFromResource(wsFill)) + { + pBrush = pState->GetBrush(wsFill); + bDeleteBrush = false; + } + else + { + pBrush = ReadBrush(wsFill.c_str(), pState->GetCurrentOpacity()); + bDeleteBrush = true; + } + } + if (bStroke) { pRenderer->put_PenColor(nStrokeBgr & 0x00FFFFFF); pRenderer->put_PenAlpha(nStrokeAlpha * pState->GetCurrentOpacity()); } - if (bFill) - { - pRenderer->put_BrushType(c_BrushTypeSolid); - pRenderer->put_BrushColor1(nFillBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1(nFillAlpha * pState->GetCurrentOpacity()); - } - if (!oReader.IsEmptyNode()) { CWString wsNodeName; @@ -725,9 +817,10 @@ namespace XPS { wsClip = ReadClip(oReader); } - else if (wsNodeName == L"Path.Fill" && !bFill) + else if (wsNodeName == L"Path.Fill" && !pBrush) { - bFill = FillToRenderer(oReader, pRenderer, pState); + pBrush = ReadBrush(oReader, pState->GetCurrentOpacity()); + bDeleteBrush = true; } else if (wsNodeName == L"Path.Stroke" && !bStroke) { @@ -740,6 +833,16 @@ namespace XPS } } + if (pBrush) + { + if (pBrush->IsImageBrush()) + ((CImageBrush*)pBrush)->SetPaths(m_wsRootPath.c_str(), GetPath(m_wsPagePath).c_str()); + + bFill = pBrush->SetToRenderer(pRenderer); + if (bDeleteBrush) + RELEASEOBJECT(pBrush); + } + // Сначала задается матрица преобразования, потом клип, потому что даже // если преобразование задано в дочерней ноде, а клип задан в атрибутах данной ноды, // то преобразование влияется на клип все равно. @@ -810,42 +913,7 @@ namespace XPS if (bOpacity) pState->PopOpacity(); - } - bool Page::FillToRenderer (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) - { - if (!oReader.IsEmptyNode()) - { - std::wstring wsNodeName; - int nCurDepth = oReader.GetDepth(); - while (oReader.ReadNextSiblingNode(nCurDepth)) - { - wsNodeName = oReader.GetName(); - wsNodeName = RemoveNamespace(wsNodeName); - - if (L"SolidColorBrush" == wsNodeName) - { - int nBgr, nAlpha; - std::wstring wsColor; - ReadAttribute(oReader, L"Color", wsColor); - GetBgra(wsColor, nBgr, nAlpha); - pRenderer->put_BrushType(c_BrushTypeSolid); - pRenderer->put_BrushColor1(nBgr & 0x00FFFFFF); - pRenderer->put_BrushAlpha1((double)nAlpha * pState->GetCurrentOpacity()); - return true; - } - else if (L"ImageBrush" == wsNodeName) - { - std::wstring wsImageSource; - ReadAttribute(oReader, L"ImageSource", wsImageSource); - pRenderer->put_BrushType(c_BrushTypeTexture); - pRenderer->put_BrushTexturePath(m_wsRootPath + wsImageSource); - return true; - } - } - } - - return false; - } + } bool Page::StrokeToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState) { if (!oReader.IsEmptyNode()) diff --git a/XpsFile/XpsLib/Page.h b/XpsFile/XpsLib/Page.h index d66990fd52..14aa41afc8 100644 --- a/XpsFile/XpsLib/Page.h +++ b/XpsFile/XpsLib/Page.h @@ -29,7 +29,6 @@ namespace XPS bool ReadResource (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); void DrawGlyph (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); void DrawPath (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); - bool FillToRenderer (XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); bool StrokeToRenderer(XmlUtils::CXmlLiteReader& oReader, IRenderer* pRenderer, CContextState* pState); void ReadPathData (XmlUtils::CXmlLiteReader& oReader, CWString& wsData, CWString& wsTranform); diff --git a/XpsFile/XpsLib/StaticResources.cpp b/XpsFile/XpsLib/StaticResources.cpp new file mode 100644 index 0000000000..63f58d60b3 --- /dev/null +++ b/XpsFile/XpsLib/StaticResources.cpp @@ -0,0 +1,408 @@ +#include "StaticResources.h" + +#include "../../Common/DocxFormat/Source/XML/xmlutils.h" +#include "../../DesktopEditor/graphics/IRenderer.h" +#include "../../DesktopEditor/graphics/structures.h" +#include "../../PdfWriter/PdfRenderer.h" +#include "../../DesktopEditor/common/File.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef xpsUnitToMM +#define xpsUnitToMM(x) ((x) * 25.4 / 96) +#endif + +namespace XPS +{ + CStaticResource::CStaticResource(const wchar_t* wsPath) + { + XmlUtils::CXmlLiteReader oReader; + + if (!oReader.FromFile(wsPath)) + return; + + Parse(oReader); + } + CStaticResource::CStaticResource(XmlUtils::CXmlLiteReader& oReader) + { + if (oReader.IsEmptyNode()) + return; + + Parse(oReader); + } + CStaticResource::~CStaticResource() + { + } + const wchar_t* CStaticResource::GetFigure(CWString& wsKey) + { + std::map::iterator oIter = m_mFigures.find(wsKey); + if (oIter != m_mFigures.end()) + return oIter->second.c_str(); + + return NULL; + } + CBrush* CStaticResource::GetBrush(CWString& wsKey) + { + std::map::iterator oIter = m_mBrushes.find(wsKey); + if (oIter != m_mBrushes.end()) + return oIter->second; + + return NULL; + } + void CStaticResource::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()) + AddFigure(wsKey, wsValue); + } + else if (wsNodeName == L"SolidColorBrush" + || wsNodeName == L"ImageBrush" + || wsNodeName == L"LinearGradientBrush" + || wsNodeName == L"RadialGradientBrush") + { + CWString wsKey; + CBrush* pBrush = ReadBrushNode(oReader, 1.0, &wsKey); + if (pBrush) + AddBrush(wsKey, pBrush); + } + } + } + void CStaticResource::AddFigure(const CWString& wsKey, const CWString& wsValue) + { + m_mFigures.insert(std::pair(wsKey, wsValue)); + } + void CStaticResource::AddBrush(const CWString& wsKey, CBrush* pBrush) + { + m_mBrushes.insert(std::pair(wsKey, pBrush)); + } + + bool CSolidBrush::SetToRenderer(IRenderer* pRenderer) + { + pRenderer->put_BrushType(c_BrushTypeSolid); + pRenderer->put_BrushColor1(m_nBgr); + pRenderer->put_BrushAlpha1(m_nAlpha); + return true; + } + bool CImageBrush::SetToRenderer(IRenderer* pRenderer) + { + std::wstring wsPath = m_wsRoot.c_str(); + wsPath += m_wsPath.c_str(); + + if (!NSFile::CFileBinary::Exists(wsPath)) + { + wsPath = m_wsPage.c_str(); + wsPath += m_wsPath.c_str(); + if (!NSFile::CFileBinary::Exists(wsPath)) + return false; + } + + pRenderer->put_BrushType(c_BrushTypeTexture); + pRenderer->put_BrushTexturePath(wsPath); + return true; + } + void CImageBrush::SetPaths(const wchar_t* wsRoot, const wchar_t* wsPage) + { + m_wsRoot.create(wsRoot, true); + m_wsPage.create(wsPage, true); + } + bool CLinearGradientBrush::SetToRenderer(IRenderer* pRenderer) + { + if (!m_pColors || !m_pPositions || !m_lCount) + return false; + + LONG lRendererType = c_nUnknownRenderer; + pRenderer->get_Type(&lRendererType); + if (c_nPDFWriter == lRendererType) + { + CPdfRenderer* pPdf = (CPdfRenderer*)pRenderer; + pPdf->put_BrushGradientColors(m_pColors, m_pPositions, m_lCount); + pPdf->SetLinearGradient(m_dX0, m_dY0, m_dX1, m_dY1); + } + else + { + double dX = m_dX1 - m_dX0, dY = m_dY1 - m_dY0; + double dHyp = sqrt(dX * dX + dY * dY); + double dAngle = acos(dX / dHyp) * 180 / M_PI; + pRenderer->put_BrushType(c_BrushTypePathGradient1); + pRenderer->put_BrushGradientColors(m_pColors, m_pPositions, m_lCount); + pRenderer->put_BrushLinearAngle(dAngle); + } + return true; + } + bool CRadialGradientBrush::SetToRenderer(IRenderer* pRenderer) + { + if (!m_pColors || !m_pPositions || !m_lCount) + return false; + + LONG lRendererType = c_nUnknownRenderer; + pRenderer->get_Type(&lRendererType); + if (c_nPDFWriter == lRendererType) + { + CPdfRenderer* pPdf = (CPdfRenderer*)pRenderer; + pPdf->put_BrushGradientColors(m_pColors, m_pPositions, m_lCount); + pPdf->SetRadialGradient(m_dXo, m_dYo, 0, m_dXc, m_dYc, max(m_dRadX, m_dRadY)); + } + else + { + pRenderer->put_BrushType(c_BrushTypePathGradient2); + pRenderer->put_BrushGradientColors(m_pColors, m_pPositions, m_lCount); + } + + return true; + } + CBrush* ReadBrushNode(XmlUtils::CXmlLiteReader& oReader, const double& dCurOpacity, CWString* pwsKey) + { + CBrush* pBrush = NULL; + CWString wsNodeName = oReader.GetName(); + if (wsNodeName == L"SolidColorBrush") + { + int nBgr = 0, nAlpha = 255; + double dOpacity = 1.0; + if (oReader.GetAttributesCount() > 0 && oReader.MoveToFirstAttribute()) + { + CWString wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"Color") + { + ReadSTColor(oReader.GetText(), nBgr, nAlpha); + } + else if (wsAttrName == L"Opacity") + { + ReadSTDouble(oReader.GetText(), dOpacity); + } + else if (wsAttrName == L"x:Key" && pwsKey) + { + pwsKey->create(oReader.GetText(), true); + } + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + oReader.MoveToElement(); + } + pBrush = new CSolidBrush(nBgr, nAlpha * dCurOpacity * dOpacity); + } + else if (wsNodeName == L"ImageBrush") + { + if (oReader.GetAttributesCount() > 0 && oReader.MoveToFirstAttribute()) + { + CWString wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"ImageSource") + { + pBrush = new CImageBrush(oReader.GetText()); + } + else if (wsAttrName == L"x:Key" && pwsKey) + { + pwsKey->create(oReader.GetText(), true); + } + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + oReader.MoveToElement(); + } + } + else if (wsNodeName == L"LinearGradientBrush" || wsNodeName == L"RadialGradientBrush") + { + bool bLinearGradient = (wsNodeName == L"LinearGradientBrush" ? true : false); + + double dOpacity = 1.0; + if (bLinearGradient) + { + double dX0 = 0, dY0 = 0, dX1 = 1, dY1 = 1; + if (oReader.GetAttributesCount() > 0 && oReader.MoveToFirstAttribute()) + { + CWString wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"StartPoint") + { + ReadSTPoint(oReader.GetText(), dX0, dY0); + } + else if (wsAttrName == L"EndPoint") + { + ReadSTPoint(oReader.GetText(), dX1, dY1); + } + else if (wsAttrName == L"Opacity") + { + CWString wsOpacity = oReader.GetText(); + + if (!wsOpacity.empty()) + dOpacity = GetDouble(wsOpacity.c_str()); + } + else if (wsAttrName == L"x:Key" && pwsKey) + { + pwsKey->create(oReader.GetText(), true); + } + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + oReader.MoveToElement(); + } + pBrush = new CLinearGradientBrush(xpsUnitToMM(dX0), xpsUnitToMM(dY0), xpsUnitToMM(dX1), xpsUnitToMM(dY1)); + } + else + { + double dX1 = 0, dY1 = 0, dRx = 0, dRy = 0, dX0 = 0, dY0 = 0; + if (oReader.GetAttributesCount() > 0 && oReader.MoveToFirstAttribute()) + { + CWString wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"Center") + { + ReadSTPoint(oReader.GetText(), dX1, dY1); + } + else if (wsAttrName == L"GradientOrigin") + { + ReadSTPoint(oReader.GetText(), dX0, dY0); + } + else if (wsAttrName == L"Opacity") + { + CWString wsOpacity = oReader.GetText(); + + if (!wsOpacity.empty()) + dOpacity = GetDouble(wsOpacity.c_str()); + } + else if (wsAttrName == L"RadiusX") + { + ReadSTDouble(oReader.GetText(), dRx); + } + else if (wsAttrName == L"RadiusY") + { + ReadSTDouble(oReader.GetText(), dRy); + } + else if (wsAttrName == L"x:Key" && pwsKey) + { + pwsKey->create(oReader.GetText(), true); + } + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + oReader.MoveToElement(); + } + pBrush = new CRadialGradientBrush(xpsUnitToMM(dX1), xpsUnitToMM(dY1), xpsUnitToMM(dX0), xpsUnitToMM(dY0), xpsUnitToMM(dRx), xpsUnitToMM(dRy)); + } + + if (!pBrush) + return NULL; + + std::vector vColors; + std::vector vPositions; + if (!oReader.IsEmptyNode()) + { + int nGrDepth = oReader.GetDepth(); + while (oReader.ReadNextSiblingNode(nGrDepth)) + { + wsNodeName = oReader.GetName(); + if ((wsNodeName == L"LinearGradientBrush.GradientStops" && bLinearGradient) + || (wsNodeName == L"RadialGradientBrush.GradientStops" && !bLinearGradient)) + { + ReadGradientStops(oReader, vColors, vPositions, dOpacity * dCurOpacity); + } + } + } + + LONG lCount = min(vColors.size(), vPositions.size()); + if (lCount <= 0) + { + delete pBrush; + return NULL; + } + + LONG* pColors = new LONG[lCount]; + if (!pColors) + { + delete pBrush; + return NULL; + } + + double* pPositions = new double[lCount]; + if (!pPositions) + { + RELEASEARRAYOBJECTS(pColors); + delete pBrush; + return NULL; + } + + for (LONG lIndex = 0; lIndex < lCount; lIndex++) + { + pColors[lIndex] = vColors[lIndex]; + pPositions[lIndex] = vPositions[lIndex]; + } + + ((CGradientBrush*)pBrush)->SetGradientStops(pColors, pPositions, lCount); + } + + return pBrush; + } + CBrush* ReadBrush(XmlUtils::CXmlLiteReader& oReader, const double& dCurOpacity, CWString* pwsKey) + { + CBrush* pBrush = NULL; + + // TODO: 1. Трансформы здесь не реализованы, потому что их невозможно учесть с текущим интерфейсом рендерера + // 2. Не реализован VisualBrush + if (!oReader.IsEmptyNode()) + { + CWString wsNodeName; + int nCurDepth = oReader.GetDepth(); + while (oReader.ReadNextSiblingNode(nCurDepth)) + { + pBrush = ReadBrushNode(oReader, dCurOpacity, pwsKey); + if (pBrush) + break; + } + } + + return pBrush; + } + CBrush* ReadBrush(const wchar_t* wsBrush, const double& dCurOpacity) + { + int nBgr, nAlpha; + ReadSTColor(wsBrush, nBgr, nAlpha); + return new CSolidBrush(nBgr, nAlpha * dCurOpacity); + } +} \ No newline at end of file diff --git a/XpsFile/XpsLib/StaticResources.h b/XpsFile/XpsLib/StaticResources.h new file mode 100644 index 0000000000..f4f2e7f0ab --- /dev/null +++ b/XpsFile/XpsLib/StaticResources.h @@ -0,0 +1,135 @@ +#ifndef _XPS_XPSLIB_STATICRESOURCES_H +#define _XPS_XPSLIB_STATICRESOURCES_H + +#include "Utils.h" +#include + +class XmlUtils::CXmlLiteReader; +class XPS::CWString; +class IRenderer; + +namespace XPS +{ + class CBrush; + class CStaticResource + { + public: + CStaticResource(const wchar_t* wsPath); + CStaticResource(XmlUtils::CXmlLiteReader& oReader); + ~CStaticResource(); + const wchar_t* GetFigure(CWString& wsKey); + CBrush* GetBrush(CWString& wsKey); + + private: + + void Parse(XmlUtils::CXmlLiteReader& oReader); + void AddFigure(const CWString& wsKey, const CWString& wsValue); + void AddBrush(const CWString& wsKey, CBrush* pBrush); + + private: + + std::map m_mFigures; + std::map m_mBrushes; + }; + + class CBrush + { + public: + CBrush(){} + virtual ~CBrush(){} + virtual bool SetToRenderer(IRenderer* pRenderer) { return false; } + virtual bool IsImageBrush() { return false; } + }; + class CSolidBrush : public CBrush + { + public: + CSolidBrush(int nBgr, int nAlpha) : m_nBgr(nBgr), m_nAlpha(nAlpha){} + bool SetToRenderer(IRenderer* pRenderer); + + private: + + int m_nBgr; + int m_nAlpha; + }; + class CImageBrush : public CBrush + { + public: + CImageBrush(const wchar_t* wsPath) + { + m_wsPath.create(wsPath, true); + } + bool SetToRenderer(IRenderer* pRenderer); + bool IsImageBrush() { return true; } + void SetPaths(const wchar_t* wsRoot, const wchar_t* wsPage); + private: + + CWString m_wsPath; + CWString m_wsRoot; + CWString m_wsPage; + }; + class CGradientBrush : public CBrush + { + public: + CGradientBrush() + { + m_pColors = NULL; + m_pPositions = NULL; + m_lCount = 0; + } + virtual ~CGradientBrush() + { + RELEASEARRAYOBJECTS(m_pColors); + RELEASEARRAYOBJECTS(m_pPositions); + } + void SetGradientStops(LONG* pColors, double* pPositions, LONG lCount) + { + m_pColors = pColors; + m_pPositions = pPositions; + m_lCount = lCount; + } + + protected: + + LONG* m_pColors; + double* m_pPositions; + LONG m_lCount; + }; + class CLinearGradientBrush : public CGradientBrush + { + public: + CLinearGradientBrush(const double& dX0, const double& dY0, const double& dX1, const double& dY1) : m_dX0(dX0), m_dY0(dY0), m_dX1(dX1), m_dY1(dY1) + { + } + bool SetToRenderer(IRenderer* pRenderer); + + private: + + double m_dX0; + double m_dY0; + double m_dX1; + double m_dY1; + }; + class CRadialGradientBrush : public CGradientBrush + { + public: + CRadialGradientBrush(const double& dXcenter, const double& dYcenter, const double& dXorigin, const double& dYorigin, const double& dRadX, const double& dRadY) : + m_dXc(dXcenter), m_dYc(dYcenter), m_dXo(dXorigin), m_dYo(dYorigin), m_dRadX(dRadX), m_dRadY(dRadY) + { + + } + bool SetToRenderer(IRenderer* pRenderer); + private: + + double m_dXc; + double m_dYc; + double m_dXo; + double m_dYo; + double m_dRadX; + double m_dRadY; + }; + CBrush* ReadBrushNode(XmlUtils::CXmlLiteReader& oReader, const double& dOpacity = 1.0, CWString* pwsKey = NULL); + CBrush* ReadBrush(XmlUtils::CXmlLiteReader& oReader, const double& dOpacity = 1.0, CWString* pwsKey = NULL); + CBrush* ReadBrush(const wchar_t* wsString, const double& dOpacity = 1.0); +} + +#endif //_XPS_XPSLIB_STATICRESOURCES_H \ No newline at end of file diff --git a/XpsFile/XpsLib/Utils.cpp b/XpsFile/XpsLib/Utils.cpp index c6aff998b1..cc7710b8bd 100644 --- a/XpsFile/XpsLib/Utils.cpp +++ b/XpsFile/XpsLib/Utils.cpp @@ -24,7 +24,9 @@ || '8' == (X)\ || '9' == (X)\ || '-' == (X)\ - || '.' == (X)) + || '.' == (X)\ + || 'e' == (X)\ + || 'E' == (X)) #define GetChar(STRING, POS) STRING[POS++] #define LookChar(STRING, POS) STRING[POS] @@ -106,6 +108,12 @@ namespace XPS dFloat = (double)nInt; goto doReal; } + else if ('e' == wChar || 'E' == wChar) + { + nPos++; + dFloat = (double)nInt; + goto doExponent; + } else { break; @@ -119,7 +127,13 @@ namespace XPS while (1) { wChar = LookChar(wsString, nPos); - if (!isdigit(wChar)) + + if ('e' == wChar || 'E' == wChar) + { + nPos++; + goto doExponent; + } + else if (!isdigit(wChar)) break; nPos++; @@ -128,6 +142,49 @@ namespace XPS } return (bNegative ? (double)(-dFloat) : (double)dFloat); + + doExponent: + + wChar = GetChar(wsString, nPos); + bool bNegativeExponent = false; + int nExp = 0; + if ('-' == wChar) + { + bNegativeExponent = true; + } + else if ('+' == wChar) + { + bNegativeExponent = false; + } + else + { + nExp = wChar - '0'; + } + + while (1) + { + wChar = LookChar(wsString, nPos); + if (!isdigit(wChar)) + break; + + nPos++; + nExp = nExp * 10 + (wChar - '0'); + } + + dFloat = (bNegative ? (double)(-dFloat) : (double)dFloat); + nExp = max(20, min(0, nExp)); + + while (nExp) + { + if (bNegativeExponent) + dFloat /= 10; + else + dFloat *= 10; + + nExp--; + } + + return dFloat; } return 0.0; @@ -312,6 +369,10 @@ namespace XPS { return (((wChar >= 'A') && (wChar <= 'Z')) || ((wChar >= 'a') && (wChar <= 'z'))); } + double GetDouble(const CWString& wsString) + { + return _wtof(wsString.c_str()); + } double GetDouble(const std::wstring& wsString) { return _wtof(wsString.c_str()); @@ -984,7 +1045,7 @@ namespace XPS else return false; // Такого не должно быть } - void ReadTransform (XmlUtils::CXmlLiteReader& oReader, CWString& wsTransform, CWString* pwsKey) + void ReadTransform (XmlUtils::CXmlLiteReader& oReader, CWString& wsTransform, CWString* pwsKey) { CWString wsNodeName; int nCurDepth = oReader.GetDepth(); @@ -1006,13 +1067,18 @@ namespace XPS wsTransform.create(oReader.GetText(), true); else if (wsAttrName == L"x:Key" && pwsKey) pwsKey->create(oReader.GetText(), true); + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); } oReader.MoveToElement(); } } } - void ReadPathGeometry(XmlUtils::CXmlLiteReader& oReader, CWString& wsData, CWString& wsTransform, CWString* pwsKey) + void ReadPathGeometry (XmlUtils::CXmlLiteReader& oReader, CWString& wsData, CWString& wsTransform, CWString* pwsKey) { bool bEvenOdd = true; CWString wsAttrName; @@ -1056,7 +1122,7 @@ namespace XPS ReadPathFigure(oReader, wsData, bEvenOdd); } } - void ReadPathFigure (XmlUtils::CXmlLiteReader& oReader, CWString& _wsData, bool bEvenOdd) + void ReadPathFigure (XmlUtils::CXmlLiteReader& oReader, CWString& _wsData, bool bEvenOdd) { // TODO: Улучшить здесь сложение строк и хождение по атрибутам std::wstring wsData; @@ -1142,4 +1208,145 @@ namespace XPS _wsData.create(wsData.c_str(), true); } + void ReadGradientStops(XmlUtils::CXmlLiteReader& oReader, std::vector& vColors, std::vector& vPositions, const double& dOpacity) + { + if (oReader.IsEmptyNode()) + return; + + CWString wsNodeName, wsAttrName; + int nCurDepth = oReader.GetDepth(); + while (oReader.ReadNextSiblingNode(nCurDepth)) + { + wsNodeName = oReader.GetName(); + if (wsNodeName == L"GradientStop") + { + double dPos = 0; + LONG lColor = 0; + if (oReader.MoveToFirstAttribute()) + { + wsAttrName = oReader.GetName(); + while (!wsAttrName.empty()) + { + if (wsAttrName == L"Color") + { + int nBgr, nAlpha; + ReadSTColor(oReader.GetText(), nBgr, nAlpha); + nAlpha *= dOpacity; + lColor = (nAlpha << 24 & 0xFF000000) | (nBgr & 0xFFFFFF); + } + else if (wsAttrName == L"Offset") + { + ReadSTDouble(oReader.GetText(), dPos); + } + + if (!oReader.MoveToNextAttribute()) + break; + + wsAttrName = oReader.GetName(); + } + + oReader.MoveToElement(); + } + vColors.push_back(lColor); + vPositions.push_back(dPos); + } + } + } + + void ReadSTPoint(const CWString& wsString, double& dX, double& dY) + { + int nCommaPos = 0; + while (nCommaPos < wsString.size()) + { + if (wsString[nCommaPos] == ',') + break; + + nCommaPos++; + } + + if (nCommaPos >= wsString.size()) + { + CWString wsX = wsString.c_str(); + dX = GetDouble(wsX); + dY = 0; + } + else + { + CWString wsX((wchar_t*)wsString.c_str(), false, nCommaPos); + CWString wsY((wchar_t*)(wsString.c_str() + nCommaPos + 1), false, wsString.size() - nCommaPos - 1); + dX = GetDouble(wsX); + dY = GetDouble(wsY); + } + } + void ReadSTColor(const CWString& wsString, int& nBgr, int& nAlpha) + { + int nLen = wsString.size(); + if (nLen <= 0) + return; + + const wchar_t* pBuffer = wsString.c_str(); + if (L'#' == pBuffer[0]) + { + nLen--; + pBuffer++; + + if (6 != nLen && 8 != nLen) + return; + + if (8 == nLen) + { + nAlpha = GetDigit(*pBuffer++); + nAlpha <<= 4; + nAlpha += GetDigit(*pBuffer++); + } + else + { + nAlpha = 255; + } + + nBgr = GetDigit(pBuffer[4]); + nBgr <<= 4; + nBgr += GetDigit(pBuffer[5]); + nBgr <<= 4; + nBgr += GetDigit(pBuffer[2]); + nBgr <<= 4; + nBgr += GetDigit(pBuffer[3]); + nBgr <<= 4; + nBgr += GetDigit(pBuffer[0]); + nBgr <<= 4; + nBgr += GetDigit(pBuffer[1]); + } + else if (nLen >= 3 && L's' == pBuffer[0] && L'c' == pBuffer[1] && L'#' == pBuffer[2]) + { + int nPos = 3; + if (nPos >= nLen) + return; + + CWString wsString2; + wsString2.create(pBuffer + 3, false); + + std::vector vElements = wsString2.split(','); + if (3 == vElements.size()) + { + nAlpha = 255; + nBgr = (((int)(min(GetDouble(vElements[2]), 1.0) * 255)) << 16) + (((int)(min(GetDouble(vElements[1]), 1.0) * 255)) << 8) + ((int)(min(GetDouble(vElements[0]), 1.0) * 255)); + } + else if (4 == vElements.size()) + { + nAlpha = (int)(min(GetDouble(vElements[0]), 1.0) * 255); + nBgr = (((int)(min(GetDouble(vElements[3]), 1.0) * 255)) << 16) + (((int)(min(GetDouble(vElements[2]), 1.0) * 255)) << 8) + ((int)(min(GetDouble(vElements[1]), 1.0) * 255)); + } + } + } + void ReadSTColor(const CWString& wsString, LONG& lColor) + { + int nBgr, nAlpha; + ReadSTColor(wsString, nBgr, nAlpha); + lColor = (nAlpha << 24 & 0xFF000000) | (nBgr & 0xFFFFFF); + } + void ReadSTDouble(const CWString& wsString, double& dValue) + { + int nPos = 0; + dValue = GetDouble(wsString.c_str(), nPos, wsString.size()); + } } \ No newline at end of file diff --git a/XpsFile/XpsLib/Utils.h b/XpsFile/XpsLib/Utils.h index 25fe73e068..3e109c7e07 100644 --- a/XpsFile/XpsLib/Utils.h +++ b/XpsFile/XpsLib/Utils.h @@ -5,6 +5,8 @@ #include #include "WString.h" +#include "../../DesktopEditor/common/Types.h" + namespace XmlUtils { class CXmlLiteReader; @@ -76,9 +78,16 @@ namespace XPS bool VmlToRenderer(const wchar_t* wsString, IRenderer* pRenderer); bool GetNextGlyph(const wchar_t* wsIndices, int& nIndicesPos, const int& nIndicesLen, unsigned short* pUtf16, int& nUtf16Pos, const int& nUtf16Len, TIndicesEntry& oEntry); + void ReadSTPoint(const CWString& wsString, double& dX, double& dY); + void ReadSTColor(const CWString& wsString, int& nBgr, int& nAlpha); + void ReadSTColor(const CWString& wsString, LONG& lColor); + void ReadSTDouble(const CWString& wsString, double& dValue); + void ReadTransform (XmlUtils::CXmlLiteReader& oReader, CWString& wsTransform, CWString* pwsKey = NULL); void ReadPathGeometry(XmlUtils::CXmlLiteReader& oReader, CWString& wsData, CWString& wsTransform, CWString* pwsKey = NULL); void ReadPathFigure (XmlUtils::CXmlLiteReader& oReader, CWString& _wsData, bool bEvenOdd); + + void ReadGradientStops(XmlUtils::CXmlLiteReader& oReader, std::vector& vColors, std::vector& vPositions, const double& dOpacity); } #endif // _XPS_XPSLIB_UTILS_H \ No newline at end of file diff --git a/XpsFile/XpsLib/WString.cpp b/XpsFile/XpsLib/WString.cpp new file mode 100644 index 0000000000..d10fd89608 --- /dev/null +++ b/XpsFile/XpsLib/WString.cpp @@ -0,0 +1,229 @@ +#include "WString.h" +#include "Utils.h" + +#include "../../DesktopEditor/common/String.h" +#include "../../DesktopEditor/common/Types.h" + +#define MAX_STRING_LEN 2147483648 + +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; + } + std::vector CWString::split(wchar_t wChar, bool bCopy) + { + std::vector vResult; + + int nPos = 0; + int nLen = size(); + int nCharPos = nPos; + while (nPos < nLen) + { + int nCharPos = nPos; + while (nCharPos < nLen && operator[](nCharPos) != wChar) + nCharPos++; + + CWString wsElement; + wsElement.create(this->c_str() + nPos, bCopy, nCharPos - nPos); + vResult.push_back(wsElement); + nPos = nCharPos + 1; + } + return vResult; + } +} \ No newline at end of file diff --git a/XpsFile/XpsLib/WString.h b/XpsFile/XpsLib/WString.h new file mode 100644 index 0000000000..800a2e3615 --- /dev/null +++ b/XpsFile/XpsLib/WString.h @@ -0,0 +1,40 @@ +#ifndef _XPS_XPSLIB_WSTRING_H +#define _XPS_XPSLIB_WSTRING_H + +#include + +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(); + + std::vector split(wchar_t wChar, bool bCopy = false); + + private: + + void* m_pBuffer; + unsigned int m_unLen; + bool m_bOwnBuffer; + }; +} + +#endif //_XPS_XPSLIB_WSTRING_H \ No newline at end of file