/* * (c) Copyright Ascensio System SIA 2010-2017 * * This program is a free software product. You can redistribute it and/or * modify it under the terms of the GNU Affero General Public License (AGPL) * version 3 as published by the Free Software Foundation. In accordance with * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect * that Ascensio System SIA expressly excludes the warranty of non-infringement * of any third-party rights. * * This program is distributed WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html * * You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, * EU, LV-1021. * * The interactive user interfaces in modified source and object code versions * of the Program must display Appropriate Legal Notices, as required under * Section 5 of the GNU AGPL version 3. * * Pursuant to Section 7(b) of the License you must retain the original Product * logo when distributing the program. Pursuant to Section 7(e) we decline to * grant you any rights under trademark law for use of our trademarks. * * All the Product's GUI elements, including illustrations and icon sets, as * well as technical writing content are licensed under the terms of the * Creative Commons Attribution-ShareAlike 4.0 International. See the License * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode * */ #pragma once #include "PathSegment.h" namespace DocFileFormat { struct _guides { unsigned char type; unsigned char param_type1; unsigned char param_type2; unsigned char param_type3; WORD param1; WORD param2; WORD param3; }; class PathParser { public: PathParser (const unsigned char* pSegmentInfo, unsigned int pSegmentInfoSize, const unsigned char* pVertices, unsigned int pVerticesSize, std::vector<_guides> & guides) { if ((pSegmentInfo != NULL) && (pSegmentInfoSize > 0)) { int offset = 6; unsigned short nElems = FormatUtils::BytesToUInt16(pSegmentInfo, 0, pSegmentInfoSize); unsigned short nElemsAlloc = FormatUtils::BytesToUInt16(pSegmentInfo, 2, pSegmentInfoSize); unsigned short cb = FormatUtils::BytesToUInt16(pSegmentInfo, 4, pSegmentInfoSize); // видимо без шапки сразу пишутся все элементы bool headerIs = ((0xfff0 != cb) && (cb > 8) || nElems > nElemsAlloc); if (headerIs) { cb = 2; offset = 0; nElems = pSegmentInfoSize / 2; for (unsigned short i = 0; i < nElems; ++i) { PathSegment oSegment = PathSegment(FormatUtils::BytesToUInt16(pSegmentInfo + offset, (i * cb), pSegmentInfoSize)); m_arSegments.push_back (oSegment); } } else { if ((0xfff0 != cb) && (8 != cb) && (4 != cb) && (2 != cb)) { cb = 0xfff0; offset = 0; nElems = pSegmentInfoSize / 2; } if (0xfff0 == cb) { cb = 4; for (unsigned short i = 0; i < nElems; ++i) { PathSegment oSegment = PathSegment(FormatUtils::BytesToUInt16(pSegmentInfo + offset, (i * cb), pSegmentInfoSize)); m_arSegments.push_back (oSegment); } } else { if ((2 != cb) && (1 != cb)) cb = 8; for (unsigned short i = 0; i < nElems; ++i) { PathSegment oSegment = PathSegment(FormatUtils::BytesToInt32(pSegmentInfo + offset, (i * cb), pSegmentInfoSize)); m_arSegments.push_back (oSegment); } if ((long)pSegmentInfoSize < (long)(cb*nElems)) // Есть несколько файлов с мусором вместо данных m_arSegments.clear(); } } } if ((NULL != pVertices) && (pVerticesSize > 0)) { unsigned short nElems = FormatUtils::BytesToUInt16(pVertices, 0, pVerticesSize); unsigned short nElemsAlloc = FormatUtils::BytesToUInt16(pVertices, 2, pVerticesSize); unsigned short cb = FormatUtils::BytesToUInt16(pVertices, 4, pVerticesSize); for (unsigned short i = 0; i < nElems; ++i) { POINT point; if (0xfff0 == cb) { cb = 4; point.x = FormatUtils::BytesToInt16(pVertices + 6, (i * cb), pVerticesSize); point.y = FormatUtils::BytesToInt16(pVertices + 6, (i * cb) + (cb / 2), pVerticesSize); } else { point.x = FormatUtils::BytesToInt32(pVertices + 6, (i * cb), pVerticesSize); point.y = FormatUtils::BytesToInt32(pVertices + 6, (i * cb) + (cb / 2), pVerticesSize); } LONG lMinF = (LONG)0x80000000; if (lMinF <= point.x) { int index = (DWORD)point.x - 0x80000000; if (index >= 0 && index < guides.size()) { point.x = guides[index].param3; } } if (lMinF <= point.y) { int index = (DWORD)point.y - 0x80000000; if (index >= 0 && index < guides.size()) { point.y = guides[index].param3; } } m_arPoints.push_back(point); } } } inline std::wstring GetVmlPath () const { if ((0 == m_arSegments.size()) && (0 == m_arPoints.size())) return std::wstring(L""); std::wstring strVmlPath; int valuePointer = 0; if (0 == m_arSegments.size()) { for (size_t i = 0; i < m_arPoints.size(); ++i) { strVmlPath += L"l"; strVmlPath += FormatUtils::IntToWideString(m_arPoints[i].x); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[i].y); ++valuePointer; } strVmlPath += L"xe"; return strVmlPath; } int cc = 0; std::vector::const_iterator end = m_arSegments.end(); for (std::vector::const_iterator iter = m_arSegments.begin(); iter != end; ++iter, cc++) { switch (iter->Type) { case PathSegment::msopathLineTo: { for (int i = 0; i < iter->Count; ++i) { if (valuePointer + 1 > (int)m_arPoints.size()) { break; strVmlPath += L"l"; strVmlPath += FormatUtils::IntToWideString(m_arPoints[0].x); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[0].y); ++valuePointer; //break; } else { strVmlPath += L"l"; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].x ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].y ); ++valuePointer; } } } break; case PathSegment::msopathCurveTo: { for (int i = 0; i < iter->Count; ++i) { if (valuePointer + 3 > (int)m_arPoints.size()) break; strVmlPath += L"c"; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].x ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].y ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer + 1].x ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer + 1].y ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer + 2].x ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer + 2].y ); valuePointer += 3; } } break; case PathSegment::msopathMoveTo: { if (valuePointer < (int)m_arPoints.size()) { strVmlPath += L"m"; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].x ); strVmlPath += L","; strVmlPath += FormatUtils::IntToWideString(m_arPoints[valuePointer].y ); ++valuePointer; } } break; case PathSegment::msopathClose: { strVmlPath += L"x"; } break; case PathSegment::msopathEnd: { strVmlPath += L"e"; } break; case PathSegment::msopathEscape: { if (PathSegment::msopathEscapeNoFill == iter->EscapeCode) strVmlPath += L"nf"; if (PathSegment::msopathEscapeNoLine == iter->EscapeCode) strVmlPath += L"ns"; } case PathSegment::msopathClientEscape: case PathSegment::msopathInvalid: { //ignore escape segments and invalid segments } break; } } // end the path if ( !strVmlPath.empty() && ( strVmlPath[strVmlPath.size() - 1] != L'e' ) ) strVmlPath +=L"e"; return strVmlPath; } private: std::vector m_arPoints; std::vector m_arSegments; }; }