/* * (c) Copyright Ascensio System SIA 2010-2023 * * 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 20A-6 Ernesta Birznieka-Upish * street, Riga, Latvia, EU, LV-1050. * * 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 * */ #include "CustomGeomShape.h" namespace NSCustomVML { CSegment::CSegment(ODRAW::RulesType eType, WORD nCount) { m_eRuler = eType; m_nCount = nCount; } CSegment::CSegment(const CSegment& oSrc) { m_eRuler = oSrc.m_eRuler; m_nCount = oSrc.m_nCount; } CSegment& CSegment::operator=(const CSegment& oSrc) { m_eRuler = oSrc.m_eRuler; m_nCount = oSrc.m_nCount; return (*this); } CSegment::~CSegment() { } int CSegment::Read(WORD value)//from rtf segments { int repeate = 0; if (value >= 0x2000 && value < 0x20FF) { repeate = value & 0x0FFF; value &= 0xFF00; } m_nCount = 0; switch (value) { case 0x0001: // lineto m_eRuler = ODRAW::rtLineTo; m_nCount = 1; break; case 0x4000: // moveto m_eRuler = ODRAW::rtMoveTo; m_nCount = 1; break; case 0x2000: // curveto m_eRuler = ODRAW::rtCurveTo; m_nCount = 3; break; case 0xb300: // arcto m_eRuler = ODRAW::rtArc; m_nCount = 0; break; case 0xac00: m_eRuler = ODRAW::rtUnknown; break; case 0xaa00: // nofill case 0xad00: m_eRuler = ODRAW::rtNoFill; break; case 0xab00: // nostroke m_eRuler = ODRAW::rtNoStroke; break; case 0x6001: // close m_eRuler = ODRAW::rtClose; break; case 0x8000: // end m_eRuler = ODRAW::rtEnd; break; default: // given number of lineto elements m_eRuler = ODRAW::rtLineTo; m_nCount = value; break; } return (std::max)(1, repeate); } void CSegment::Read(POLE::Stream* pStream)//from binary ms segments { WORD mem = StreamUtils::ReadWORD(pStream); BYTE type = mem & 0x07; if (type <= 4) { m_eRuler = (ODRAW::RulesType)type; m_nCount = (mem >> 3) & 0x1FFF; return; } mem = (mem >> 3) & 0x1FFF; type = mem & 0x1F; switch (type) { case 0x00: { m_eRuler = ODRAW::rtLineTo; break; } case 0x01: { m_eRuler = ODRAW::rtAngleEllipseTo; break; } case 0x02: { m_eRuler = ODRAW::rtAngleEllipse; break; } case 0x03: { m_eRuler = ODRAW::rtArcTo; break; } case 0x04: { m_eRuler = ODRAW::rtArc; break; } case 0x05: { m_eRuler = ODRAW::rtClockwiseArcTo; break; } case 0x06: { m_eRuler = ODRAW::rtClockwiseArc; break; } case 0x07: { m_eRuler = ODRAW::rtEllipticalQuadrX; break; } case 0x08: { m_eRuler = ODRAW::rtEllipticalQuadrY; break; } case 0x09: { m_eRuler = ODRAW::rtQuadrBesier; break; } case 0x0A: { m_eRuler = ODRAW::rtNoFill; break; } case 0x0B: { m_eRuler = ODRAW::rtNoStroke; break; } case 0x15: { m_eRuler = ODRAW::rtFillColor; break; } case 0x16: { m_eRuler = ODRAW::rtLineColor; break; } default: { m_eRuler = ODRAW::rtCurveTo; } }; m_nCount = (mem >> 5) & 0x00FF; } void CSegment::Read(ODRAW::CBinaryReader& oReader)//from binary ms segments { WORD mem = oReader.ReadWORD(); BYTE type = (mem >> 13 & 0x07); if (type <= 4) { m_eRuler = (ODRAW::RulesType)type; m_nCount = (mem & 0x1FFF); m_nCount = (WORD)GetCountPoints2(m_eRuler, m_nCount); return; } type = (mem >> 8) & 0x1F; mem = mem & 0xFF; switch (type) { case 0x00: { m_eRuler = ODRAW::rtLineTo; break; } case 0x01: { m_eRuler = ODRAW::rtAngleEllipseTo; break; } case 0x02: { m_eRuler = ODRAW::rtAngleEllipse; break; } case 0x03: { m_eRuler = ODRAW::rtArcTo; break; } case 0x04: { m_eRuler = ODRAW::rtArc; break; } case 0x05: { m_eRuler = ODRAW::rtClockwiseArcTo; break; } case 0x06: { m_eRuler = ODRAW::rtClockwiseArc; break; } case 0x07: { m_eRuler = ODRAW::rtEllipticalQuadrX; break; } case 0x08: { m_eRuler = ODRAW::rtEllipticalQuadrY; break; } case 0x09: { m_eRuler = ODRAW::rtQuadrBesier; break; } case 0x0A: { m_eRuler = ODRAW::rtNoFill; break; } case 0x0B: { m_eRuler = ODRAW::rtNoStroke; break; } case 0x0C: case 0x10: { m_eRuler = ODRAW::rtLineTo; break; } case 0x0D: case 0x0E: case 0x0F: case 0x11: case 0x12: case 0x13: case 0x14: { m_eRuler = ODRAW::rtCurveTo; break; } case 0x15: { m_eRuler = ODRAW::rtFillColor; break; } case 0x16: { m_eRuler = ODRAW::rtLineColor; break; } default: { m_eRuler = ODRAW::rtCurveTo; } }; m_nCount = (WORD)mem; m_nCount = (WORD)GetCountPoints2(m_eRuler, m_nCount); //m_nCount = (WORD)GetCountPoints2(m_eRuler); } CGuide::CGuide() { m_eType = NSGuidesVML::ftVal; m_param_type1 = 0; m_param_type2 = 0; m_param_type3 = 0; m_param_value1 = 0; m_param_value2 = 0; m_param_value3 = 0; m_lShapeWidth = ShapeSizeVML; m_lShapeHeight = ShapeSizeVML; } CGuide::CGuide(const CGuide& oSrc) { *this = oSrc; } CGuide& CGuide::operator=(const CGuide& oSrc) { m_eType = oSrc.m_eType; m_param_type1 = oSrc.m_param_type1; m_param_type2 = oSrc.m_param_type2; m_param_type3 = oSrc.m_param_type3; m_param_value1 = oSrc.m_param_value1; m_param_value2 = oSrc.m_param_value2; m_param_value3 = oSrc.m_param_value3; m_lShapeWidth = oSrc.m_lShapeWidth; m_lShapeHeight = oSrc.m_lShapeHeight; return *this; } void CGuide::SetToFormula(NSGuidesVML::CFormula& oFormula) { oFormula.m_eFormulaType = m_eType; SetParam(m_param_type1, m_param_value1, oFormula.m_eType1, oFormula.m_lParam1); SetParam(m_param_type2, m_param_value2, oFormula.m_eType2, oFormula.m_lParam2); SetParam(m_param_type3, m_param_value3, oFormula.m_eType3, oFormula.m_lParam3); } void CGuide::Read(POLE::Stream* pStream) { WORD ftType = StreamUtils::ReadWORD(pStream); m_eType = NSGuidesVML::FormulaType(ftType & 0x1FFF); m_param_type1 = (BYTE)(ftType & 0x04); m_param_type2 = (BYTE)(ftType & 0x02); m_param_type3 = (BYTE)(ftType & 0x01); m_param_value1 = StreamUtils::ReadWORD(pStream); m_param_value2 = StreamUtils::ReadWORD(pStream); m_param_value3 = StreamUtils::ReadWORD(pStream); } void CGuide::Read(ODRAW::CBinaryReader& oReader) { WORD ftType = oReader.ReadWORD(); m_eType = NSGuidesVML::FormulaType(ftType & 0x1FFF); m_param_type1 = (BYTE)(ftType & 0x04); m_param_type2 = (BYTE)(ftType & 0x02); m_param_type3 = (BYTE)(ftType & 0x01); m_param_value1 = oReader.ReadWORD(); m_param_value2 = oReader.ReadWORD(); m_param_value3 = oReader.ReadWORD(); } void CGuide::SetParam(BYTE type, WORD param, ParamType& param_type, LONG& param_value) { if (0 == type) { param_type = ptValue; param_value = (LONG)param; } if (0x0140 == param) { param_type = ptValue; param_value = ShapeSizeVML / 2; return; } if (0x0141 == param) { param_type = ptValue; param_value = ShapeSizeVML / 2; return; } if (0x0142 == param) { param_type = ptValue; param_value = ShapeSizeVML; return; } if (0x0143 == param) { param_type = ptValue; param_value = ShapeSizeVML; return; } if ((0x0147 <= param) && (param <= 0x014E)) { param_type = ptAdjust; param_value = (LONG)(param - 0x0147); return; } if ((0x0400 <= param) && (param <= 0x047F)) { param_type = ptFormula; param_value = (LONG)(param - 0x0400); return; } param_type = ptValue; param_value = ShapeSizeVML; } CCustomVML::CCustomVML() : m_arVertices(), m_arSegments(), m_arGuides(), m_pAdjustValues(NULL) { m_ePath = ODRAW::rtCurveTo/*rtLineTo*/; m_bIsVerticesPresent = false; m_bIsPathPresent = false; } CCustomVML::CCustomVML(const CCustomVML& oSrc) { *this = oSrc; } CCustomVML& CCustomVML::operator=(const CCustomVML& oSrc) { m_ePath = oSrc.m_ePath; m_arVertices.clear(); m_arVertices.insert(m_arVertices.end(), oSrc.m_arVertices.begin(), oSrc.m_arVertices.end()); m_arSegments.clear(); m_arSegments.insert(m_arSegments.end(), oSrc.m_arSegments.begin(), oSrc.m_arSegments.end()); m_arGuides.clear(); m_arGuides.insert(m_arGuides.end(), oSrc.m_arGuides.begin(), oSrc.m_arGuides.end()); m_pAdjustValues = oSrc.m_pAdjustValues; m_bIsPathPresent = oSrc.m_bIsPathPresent; m_bIsVerticesPresent = oSrc.m_bIsVerticesPresent; m_oBrush = oSrc.m_oBrush; m_oPen = oSrc.m_oPen; return *this; } CCustomVML::~CCustomVML() { } bool CCustomVML::IsCustom() { return ((m_bIsVerticesPresent || !m_arVertices.empty()) && (m_bIsPathPresent || !m_arSegments.empty())); } void CCustomVML::SetPath(ODRAW::RulesType ePath) { m_ePath = ePath; m_bIsPathPresent = true; } void CCustomVML::LoadAHs(CProperty* pProperty) { } void CCustomVML::addSegment(ODRAW::RulesType eRuler, _UINT16 nCount) { CSegment oInfo(eRuler, nCount); m_arSegments.push_back(oInfo); } void CCustomVML::addGuide(CGuide & oInfo) { m_arGuides.push_back(oInfo); } void CCustomVML::addAdjust(int lIndex, int lValue) { if (NULL == m_pAdjustValues) return; size_t lCount = m_pAdjustValues->size(); while (lCount <= lIndex) { m_pAdjustValues->push_back(0); lCount = m_pAdjustValues->size(); } (*m_pAdjustValues)[lIndex] = lValue; } void CCustomVML::SetAdjusts(std::vector* pValues) { m_pAdjustValues = pValues; } void CCustomVML::ToCustomShape(ODRAW::CBaseShape* pShape, NSGuidesVML::CFormulasManager& oManager) { if ((NULL == pShape) || (!IsCustom())) return; oManager.Clear(); // сначала заполним формулы for (size_t nIndex = 0; nIndex < m_arGuides.size(); ++nIndex) { NSGuidesVML::CFormula oF; m_arGuides[nIndex].SetToFormula(oF); oManager.AddFormula(oF); } oManager.Clear(m_pAdjustValues); std::wstring strPath = _T(""); bool bBreak = false; long lMinF = (_INT32)0x80000000; long lMaxF = (_INT32)0x8000007F; int nGuideIndex_x , nGuideIndex_y; if (0 == m_arSegments.size()) { strPath = GetRulerVML(m_ePath); for (size_t nIndex = 0; nIndex < m_arVertices.size(); ++nIndex) { nGuideIndex_x = nGuideIndex_y = -1; if (lMaxF > m_arVertices[nIndex].x ) nGuideIndex_x = (_UINT32)m_arVertices[nIndex].x - (_UINT32)lMinF; if (lMaxF > m_arVertices[nIndex].y ) nGuideIndex_y = (_UINT32)m_arVertices[nIndex].y - (_UINT32)lMinF; if (nGuideIndex_x >= 0 && nGuideIndex_x < (int)m_arGuides.size()) { strPath += std::to_wstring(m_arGuides[nGuideIndex_x].m_param_value1) + L","; } else { strPath += std::to_wstring(m_arVertices[nIndex].x) + L","; } if (nGuideIndex_y >= 0 && nGuideIndex_y < (int)m_arGuides.size()) { strPath += std::to_wstring(m_arGuides[nGuideIndex_y].m_param_value1) + L","; } else { strPath += std::to_wstring(m_arVertices[nIndex].y) + L","; } } strPath.erase(strPath.length() - 1); } else { size_t nStart = 0; size_t nEnd = 0; for (size_t nS = 0; nS < m_arSegments.size(); ++nS) { if (bBreak) { if ((ODRAW::rtEnd != m_arSegments[nS].m_eRuler) && (ODRAW::rtNoFill != m_arSegments[nS].m_eRuler) && (ODRAW::rtNoStroke != m_arSegments[nS].m_eRuler) && (ODRAW::rtClose != m_arSegments[nS].m_eRuler)) { strPath += _T("e"); break; } } if ((ODRAW::rtFillColor == m_arSegments[nS].m_eRuler) || (ODRAW::rtLineColor == m_arSegments[nS].m_eRuler)) { if (nStart < m_arVertices.size()) { if (ODRAW::rtFillColor == m_arSegments[nS].m_eRuler) { m_oBrush.Color1 = (_UINT32)m_arVertices[nStart].x; m_oBrush.Color2 = (_UINT32)m_arVertices[nStart].y; } else { m_oPen.Color = (_UINT32)m_arVertices[nStart].x; } } nEnd = nStart + m_arSegments[nS].m_nCount; if (nEnd > m_arVertices.size()) nEnd = m_arVertices.size(); nStart = nEnd; if (nEnd == m_arVertices.size()) { bBreak = true; } continue; } strPath += GetRulerVML(m_arSegments[nS].m_eRuler); nEnd = nStart + m_arSegments[nS].m_nCount; if (nEnd > m_arVertices.size()) nEnd = m_arVertices.size(); for (size_t nV = nStart; nV < nEnd; ++nV) { nGuideIndex_x = nGuideIndex_y = -1; if (lMaxF > m_arVertices[nV].x ) nGuideIndex_x = (_UINT32)m_arVertices[nV].x - (_UINT32)lMinF; if (lMaxF > m_arVertices[nV].y ) nGuideIndex_y = (_UINT32)m_arVertices[nV].y - (_UINT32)lMinF; std::wstring str = _T(""); if (nGuideIndex_x >= 0 && nGuideIndex_x < (int)m_arGuides.size()) { strPath += std::to_wstring(m_arGuides[nGuideIndex_x].m_param_value1) + L","; } else { strPath += std::to_wstring(m_arVertices[nV].x) + L","; } if (nGuideIndex_y >= 0 && nGuideIndex_y < (int)m_arGuides.size()) { strPath += std::to_wstring(m_arGuides[nGuideIndex_y].m_param_value1) + L","; } else { strPath += std::to_wstring(m_arVertices[nV].y) + L","; } } if (nEnd != nStart) { strPath.erase(strPath.length() - 1); } nStart = nEnd; if (nEnd == m_arVertices.size()) { bBreak = true; } } } oManager.CalculateResults(); pShape->LoadPathList(strPath); /*std::wstring str = _T("\ \ \ \ ");*/ //pShape->LoadFromXML(str); } void CCustomVML::LoadVertices(std::vector> values) { if (!values.empty()) m_bIsVerticesPresent = true; m_arVertices.clear(); for (size_t ind = 0; ind < values.size(); ++ind) { Aggplus::POINT oPoint; oPoint.x = values[ind].first; oPoint.y = values[ind].second; LONG lMinF = (LONG)0x80000000; LONG lMaxF = (LONG)0x8000007F; if (lMinF <= oPoint.x) { int nGuideIndex = (_UINT32)oPoint.x - 0x80000000; bool b = false; } if (lMinF <= oPoint.y) { int nGuideIndex = (_UINT32)oPoint.y - 0x80000000; bool b = false; } m_arVertices.push_back(oPoint); } } void CCustomVML::LoadConnectionSitesDir(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); m_arConnectionSitesDir.clear(); WORD lCount = (WORD)(pProperty->m_lValue / 4); for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { _UINT32 v = oReader.ReadLONG(); double val = (double)((WORD)(v >> 16) + ((WORD)(v) / 65536.0)); m_arConnectionSitesDir.push_back(val); } } void CCustomVML::LoadConnectionSites(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); m_arConnectionSites.clear(); WORD lCount = (WORD)(pProperty->m_lValue / 8); if (pProperty->m_bIsTruncated) { lCount = (WORD)(pProperty->m_lValue / 4); } for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { Aggplus::POINT oPoint; if (pProperty->m_bIsTruncated) { oPoint.x = (short)oReader.ReadWORD(); oPoint.y = (short)oReader.ReadWORD(); } else { oPoint.x = oReader.ReadLONG(); oPoint.y = oReader.ReadLONG(); } LONG lMinF = (LONG)0x80000000; LONG lMaxF = (LONG)0x8000007F; if (lMinF <= oPoint.x) { int nGuideIndex = (_UINT32)oPoint.x - 0x80000000; bool b = false; } if (lMinF <= oPoint.y) { int nGuideIndex = (_UINT32)oPoint.y - 0x80000000; bool b = false; } m_arConnectionSites.push_back(oPoint); } } void CCustomVML::LoadVertices(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); m_arVertices.clear(); WORD lCount = (WORD)(pProperty->m_lValue / 8); if (pProperty->m_bIsTruncated) { lCount = (WORD)(pProperty->m_lValue / 4); } if (lCount > 0) { m_bIsVerticesPresent = true; } for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { Aggplus::POINT oPoint; if (pProperty->m_bIsTruncated) { oPoint.x = (short)oReader.ReadWORD(); oPoint.y = (short)oReader.ReadWORD(); } else { oPoint.x = oReader.ReadLONG(); oPoint.y = oReader.ReadLONG(); } LONG lMinF = (LONG)0x80000000; LONG lMaxF = (LONG)0x8000007F; if (lMinF <= oPoint.x) { int nGuideIndex = (_UINT32)oPoint.x - 0x80000000; bool b = false; } if (lMinF <= oPoint.y) { int nGuideIndex = (_UINT32)oPoint.y - 0x80000000; bool b = false; } m_arVertices.push_back(oPoint); } } void CCustomVML::LoadSegments(std::vector values) { m_arSegments.clear(); if (!values.empty()) m_bIsPathPresent = true; for (size_t ind = 0; ind < values.size(); ++ind) { CSegment oInfo; int count = oInfo.Read(values[ind]); if (0 == oInfo.m_nCount) { if ((ODRAW::rtEnd != oInfo.m_eRuler) && (ODRAW::rtNoFill != oInfo.m_eRuler) && (ODRAW::rtNoStroke != oInfo.m_eRuler) && (ODRAW::rtClose != oInfo.m_eRuler)) { continue; } } for (int i = 0 ; i < count; i++) m_arSegments.push_back(oInfo); } } void CCustomVML::LoadSegments(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); m_arSegments.clear(); WORD lCount = (WORD)(pProperty->m_lValue / 2); if (lCount > 0) m_bIsPathPresent = true; for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { CSegment oInfo; oInfo.Read(oReader); if (0 == oInfo.m_nCount) { if ((ODRAW::rtEnd != oInfo.m_eRuler) && (ODRAW::rtNoFill != oInfo.m_eRuler) && (ODRAW::rtNoStroke != oInfo.m_eRuler) && (ODRAW::rtClose != oInfo.m_eRuler)) { continue; } } //if (rtClose == oInfo.m_eRuler) //{ // // проводим линию // CSegment oInfo2(rtLineTo, 1); // m_arSegments.push_back(oInfo2); //} m_arSegments.push_back(oInfo); } } void CCustomVML::LoadGuides(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); WORD lCount = (WORD)(pProperty->m_lValue / 4); for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { CGuide oInfo; oInfo.Read(oReader); m_arGuides.push_back(oInfo); } } void CCustomVML::LoadInscribe(CProperty* pProperty) { ODRAW::CBinaryReader oReader(pProperty->m_pOptions, pProperty->m_lValue); m_arInscribe.clear(); WORD lCount = (WORD)(pProperty->m_lValue / 16); if (pProperty->m_bIsTruncated) { lCount = (WORD)(pProperty->m_lValue / 8); } for (WORD lIndex = 0; lIndex < lCount; ++lIndex) { Aggplus::RECT oRect; if (pProperty->m_bIsTruncated) { oRect.left = (short)oReader.ReadWORD(); oRect.right = (short)oReader.ReadWORD(); oRect.top = (short)oReader.ReadWORD(); oRect.bottom = (short)oReader.ReadWORD(); } else { oRect.left = (short)oReader.ReadLONG(); oRect.right = (short)oReader.ReadLONG(); oRect.top = (short)oReader.ReadLONG(); oRect.bottom = (short)oReader.ReadLONG(); } m_arInscribe.push_back(oRect); } } void CCustomVML::LoadAdjusts(LONG lIndex, LONG lValue) { if (NULL == m_pAdjustValues) return; LONG lCount = (LONG)m_pAdjustValues->size(); while (lCount <= lIndex) { m_pAdjustValues->push_back(0); lCount = (LONG)m_pAdjustValues->size(); } (*m_pAdjustValues)[lIndex] = lValue; } }