/* * (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 "smcustomshapepars.h" namespace OdfCustomShape { SMCustomShapePars::SMCustomShapePars() {} SMCustomShapePars::~SMCustomShapePars() { for(CElement* pElement:m_arVecElements) delete pElement; } void SMCustomShapePars::StartParsSMCustomShape(const std::wstring & wsFormula, const std::wstring& wsLeft,const std::wstring& wsTop,const std::wstring& wsRight,const std::wstring& wsBottom) { CSMReader* pReader = new CSMReader(wsFormula,wsLeft,wsTop,wsRight,wsBottom); SMCustomShapePars::ParsString(pReader, m_arVecElements); return; } CElement* SMCustomShapePars::ParseElement(CSMReader* pReader) { CElement* pElement(nullptr); if(!pReader->GetElement().empty()) pElement = CElement::CreateElement(pReader->GetElement()); else pElement = pReader->ReadingElement(); if(pElement != nullptr) pElement->Parse(pReader); return pElement; } void SMCustomShapePars::ParsString(CSMReader* pReader, std::vector& arVec) { while(!pReader->CheckIteratorPosition()) { CElement* pElement = SMCustomShapePars::ParseElement(pReader); if(pElement != nullptr) { if(pElement->GetBaseType() == TypeElement::ArithmeticOperation && !arVec.empty() && arVec.back()->GetBaseType() != TypeElement::comma) { CElementArithmeticOperations* pSign = static_cast(pElement); pSign->SetFirstValue(arVec.back()); arVec.pop_back(); } arVec.push_back(pElement); } } if(!pReader->GetElement().empty()) { CElement* pElement = SMCustomShapePars::ParseElement(pReader); if(pElement != nullptr) { if(pElement->GetBaseType() == TypeElement::ArithmeticOperation && !arVec.empty()) { CElementArithmeticOperations* pSign = static_cast(pElement); pSign->SetFirstValue(arVec.back()); arVec.pop_back(); } arVec.push_back(pElement); } } } std::vector& SMCustomShapePars::GetVector() { return m_arVecElements; } //class CElemnt CElement::CElement():m_wsNameFormula(L"") {} CElement::~CElement() {} CElement *CElement::CreateElement(const std::wstring& wsElement) { if(CElementNumber::CheckNumber(wsElement)) return new CElementNumber(wsElement); else if(CElementArithmeticOperations::CheckArithmeticOperators(wsElement) || wsElement == L"--") return new CElementArithmeticOperations(wsElement); else if(wsElement == L"(") return new CElementBracket(); else if(wsElement == L",") return new CElementComma(); TypeElement enType = CElementFunction::TypeCheckingByFunction(wsElement); if(enType != TypeElement::empty) return new CElementFunction(enType); if(!wsElement.empty()) return new CElementNumber(wsElement); return nullptr; } void CElement::SetBaseType(const TypeElement& enType) { m_enBaseType = enType; } TypeElement CElement::GetBaseType() { return m_enBaseType; } void CElement::SetNameFormula(const std::wstring& wsNameFormula) { m_wsNameFormula = wsNameFormula; } std::wstring CElement::GetNameFormula() { return m_wsNameFormula; } //class CElementNumber CElementNumber::CElementNumber():m_wsNumber(L"") {} CElementNumber::CElementNumber(const std::wstring& wsName):m_wsNumber(wsName) { SetBaseType(TypeElement::NumberOrName); } CElementNumber::~CElementNumber() {} void CElementNumber::Parse(CSMReader *pReader) { if(!pReader->GetElement().empty()) pReader->ClearElement(); if(m_wsNumber == L"left") m_wsNumber = pReader->GetLeft() != L"" ? pReader->GetLeft():L"l"; else if(m_wsNumber == L"top") m_wsNumber = pReader->GetTop() != L"" ? pReader->GetTop():L"t"; else if(m_wsNumber == L"right") m_wsNumber = pReader->GetRight() != L"" ? pReader->GetRight():L"r"; else if(m_wsNumber == L"bottom") m_wsNumber = pReader->GetBottom() != L"" ? pReader->GetBottom():L"b"; /*The height and width may be different*/ else if(m_wsNumber == L"height") m_wsNumber = L"h"; else if(m_wsNumber == L"width") m_wsNumber = L"w"; else if(m_wsNumber[0] == L'\u0024' && m_wsNumber.size() >1) m_wsNumber = m_wsNumber.substr(1,m_wsNumber.size()); else if(m_wsNumber == L"L\u0024") m_wsNumber = L"0"; } bool CElementNumber::CheckNumber(const std::wstring& wsNumber) { if(wsNumber.empty()) return false; if(wsNumber.size() > 2 && wsNumber[0] == L'?' && wsNumber[1] == L'f') return true; for(unsigned int i = 0;i < wsNumber.size();i++) { if(!iswdigit(wsNumber[i])) return false; } return true; } void CElementNumber::ConversionOOXml(XmlUtils::CXmlWriter* pXmlWriter, const std::wstring &wsName) { if(m_wsNumber[0] == L'?' && m_wsNumber[1] == L'f') m_wsNumber.replace(0,2,L"gd"); pXmlWriter->WriteString(m_wsNumber + L" "); } std::wstring CElementNumber::GetString() { if(m_wsNumber[0] == L'?' && m_wsNumber[1] == L'f') m_wsNumber.replace(0,2,L"gd"); return m_wsNumber; } //CElementArithmeticOperations CElementArithmeticOperations::CElementArithmeticOperations():m_enTypeSign(TypeElement::empty),m_pSecondSign(nullptr),m_pFirstValue(nullptr),m_pSecondValue(nullptr),m_uiNumberFormula(1) {} CElementArithmeticOperations::CElementArithmeticOperations(const std::wstring& wsSign):m_enTypeSign(TypeElement::empty),m_pSecondSign(nullptr),m_pFirstValue(nullptr),m_pSecondValue(nullptr),m_uiNumberFormula(1) { m_enTypeSign = wsSign ==L"--" ? TypeElement::plus:CElementArithmeticOperations::SetTypeSign(wsSign); SetBaseType(TypeElement::ArithmeticOperation); } CElementArithmeticOperations::~CElementArithmeticOperations() { delete m_pFirstValue; delete m_pSecondValue; delete m_pSecondSign; } void CElementArithmeticOperations::Parse(CSMReader *pReader) { if(!pReader->GetElement().empty()) pReader->ClearElement(); CElement* pElement = SMCustomShapePars::ParseElement(pReader); if(pElement == nullptr) return; pReader->ReadingNextElement(); if(pElement->GetBaseType() != TypeElement::ArithmeticOperation && pElement->GetBaseType() != TypeElement::comma && !ComparingPriorities(pReader->GetElement())) { m_pSecondValue = pElement; pElement = nullptr; } else if(pElement->GetBaseType() == TypeElement::ArithmeticOperation && ComparisonSign(pElement)) { m_pSecondSign = pElement; pElement = nullptr; } else if(ComparingPriorities(pReader->GetElement())) { CElement* pTempElement = SMCustomShapePars::ParseElement(pReader); if(pTempElement->GetBaseType() == TypeElement::ArithmeticOperation) { CElementArithmeticOperations* pTempArithOp = dynamic_cast(pTempElement); pTempArithOp->SetFirstValue(pElement); pElement = nullptr; m_pSecondValue = pTempArithOp; } else m_pSecondValue = pTempElement; } if(!pReader->GetDoubleSign()&& !pReader->GetElement().empty() && ComparisonSign(pReader->GetElement())) { pReader->SetDoubleSign(true); CElement* pSecondSign = SMCustomShapePars::ParseElement(pReader); if(pSecondSign != nullptr) m_pSecondSign = pSecondSign; pReader->SetDoubleSign(false); } if(pElement != nullptr) { if(m_pFirstValue == nullptr) m_pFirstValue = pElement; else if(m_pSecondValue == nullptr) m_pSecondValue = pElement; } } void CElementArithmeticOperations::ConversionOOXml(XmlUtils::CXmlWriter* pXmlWriter, const std::wstring &wsName) { if(wsName != L"") SetNameFormula(wsName); if(m_pSecondSign != nullptr) { CElementArithmeticOperations* pTemp = dynamic_cast(m_pSecondSign); std::wstring wsNameValueSecondSign(L""),wsNameFirstValue(L""),wsNameSecondValue(L""); if(pTemp->GetSecondValue() != nullptr) wsNameValueSecondSign = ConversionValueSign(pXmlWriter,pTemp->GetSecondValue()); if(m_pFirstValue != nullptr) wsNameFirstValue = ConversionValueSign(pXmlWriter,m_pFirstValue); if(m_pSecondValue != nullptr) wsNameSecondValue = ConversionValueSign(pXmlWriter,m_pSecondValue); pXmlWriter->WriteNodeBegin(L"a:gd",true); if(!GetNameFormula().empty()) pXmlWriter->WriteAttribute(L"name",GetNameFormula()); else pXmlWriter->WriteAttribute(L"name",L"Unknown"); pXmlWriter->WriteString(L" fmla=\""); SignRecording(pXmlWriter,m_enTypeSign); SignRecording(pXmlWriter,pTemp->GetTypeSign()); pXmlWriter->WriteString(L" "); RecordingTheValuesSign(pXmlWriter,wsNameFirstValue,wsNameSecondValue); if(!wsNameValueSecondSign.empty()) pXmlWriter->WriteString(wsNameValueSecondSign + L" "); else if(pTemp->GetSecondValue() != nullptr) pTemp->GetSecondValue()->ConversionOOXml(pXmlWriter); else if(pTemp->GetTypeSign() == TypeElement::division) pXmlWriter->WriteString(L"1 "); else pXmlWriter->WriteString(L"0 "); pXmlWriter->WriteString(L"\""); pXmlWriter->WriteNodeEnd(L"",true,true); } else { bool bPlusMultiplication(false),bMinusDivision(false); std::wstring wsNameFirstValue(L""), wsNameSecondValue(L""); if(m_pFirstValue != nullptr) wsNameFirstValue = ConversionValueSign(pXmlWriter,m_pFirstValue); if(m_pSecondValue != nullptr) wsNameSecondValue = ConversionValueSign(pXmlWriter,m_pSecondValue); pXmlWriter->WriteNodeBegin(L"a:gd",true); if(!GetNameFormula().empty()) pXmlWriter->WriteAttribute(L"name",GetNameFormula()); else pXmlWriter->WriteAttribute(L"name",L"Unknown"); pXmlWriter->WriteString(L" fmla=\""); switch(m_enTypeSign) { case TypeElement::multiplication: case TypeElement::plus: { SignRecording(pXmlWriter,m_enTypeSign); pXmlWriter->WriteString(L"/"); bPlusMultiplication = true; break; } case TypeElement::division: case TypeElement::minus: { pXmlWriter->WriteString(L"+"); SignRecording(pXmlWriter,m_enTypeSign); bMinusDivision = true; break; } default: break; } pXmlWriter->WriteString(L" "); if(bPlusMultiplication) { RecordingTheValuesSign(pXmlWriter,wsNameFirstValue,wsNameSecondValue); pXmlWriter->WriteString(L"1 "); } else if(bMinusDivision) { pXmlWriter->WriteString(L"0 "); RecordingTheValuesSign(pXmlWriter,wsNameFirstValue,wsNameSecondValue); } pXmlWriter->WriteString(L"\""); pXmlWriter->WriteNodeEnd(L"",true,true); } } bool CElementArithmeticOperations::CheckArithmeticOperators(const std::wstring& wsElement) { if(wsElement.empty()) return false; if(wsElement.size() == 1) { switch (wsElement[0]) { case L'+': case L'-': case L'*': case L'/': return true; default: return false; } } else return false; } //Нет сравнения + и / bool CElementArithmeticOperations::ComparisonSign(const std::wstring& wsSign) { return((m_enTypeSign == TypeElement::multiplication && wsSign == L"/") || (m_enTypeSign == TypeElement::plus && wsSign == L"-")); } bool CElementArithmeticOperations::ComparisonSign(CElement *pElement) { if(pElement == nullptr) return false; if(pElement->GetBaseType() == TypeElement::ArithmeticOperation) { CElementArithmeticOperations* pSign = dynamic_cast(pElement); return((m_enTypeSign == TypeElement::plus && pSign->GetTypeSign() == TypeElement::minus) || (m_enTypeSign == TypeElement::multiplication && pSign->GetTypeSign() == TypeElement::division)); } else return false; } bool CElementArithmeticOperations::ComparingPriorities(const std::wstring& wsSign) { return ((m_enTypeSign == TypeElement::plus || m_enTypeSign == TypeElement::minus) && (wsSign == L"/" || wsSign == L"*")); } void CElementArithmeticOperations::SetFirstValue(CElement* pElement) { m_pFirstValue = pElement; } TypeElement CElementArithmeticOperations::SetTypeSign(const std::wstring& wsSign) { if(wsSign.size() > 1) return TypeElement::empty; switch (wsSign[0]) { case '+': return TypeElement::plus; case '-': return TypeElement::minus; case '/': return TypeElement::division; case '*': return TypeElement::multiplication; default: return TypeElement::empty; } } TypeElement CElementArithmeticOperations::GetTypeSign() { return m_enTypeSign; } void CElementArithmeticOperations::SignRecording(XmlUtils::CXmlWriter* pXmlWriter, const TypeElement& enTypeSign) { switch (enTypeSign) { case TypeElement::multiplication: pXmlWriter->WriteString(L"*"); break; case TypeElement::plus: pXmlWriter->WriteString(L"+"); break; case TypeElement::minus: pXmlWriter->WriteString(L"-"); break; case TypeElement::division: pXmlWriter->WriteString(L"/"); break; default: break; } } CElement* CElementArithmeticOperations::GetSecondValue() { return m_pSecondValue; } std::wstring CElementArithmeticOperations::ConversionValueSign(XmlUtils::CXmlWriter *pXmlWriter, CElement* pElement) { if(pElement->GetBaseType() == TypeElement::NumberOrName) return L""; else if(pElement->GetBaseType()== TypeElement::Bracket) { CElementBracket* pTempBracket = dynamic_cast(pElement); std::vector arTemp = pTempBracket->GetVector(); if(!arTemp.empty() && arTemp.size() == 1 && arTemp[0]->GetBaseType() == TypeElement::NumberOrName ) return L""; else { std::wstring wsTempName,wsOldName = GetNameFormula(); CElementFunction::CalculatingNumberName(wsTempName,wsOldName,m_uiNumberFormula); pElement->ConversionOOXml(pXmlWriter,wsTempName); return pElement->GetNameFormula(); } } else { std::wstring wsTempName,wsOldName = GetNameFormula(); CElementFunction::CalculatingNumberName(wsTempName,wsOldName,m_uiNumberFormula); pElement->ConversionOOXml(pXmlWriter,wsTempName); return pElement->GetNameFormula(); } return L""; } void CElementArithmeticOperations::RecordingTheValuesSign(XmlUtils::CXmlWriter *pXmlWriter, const std::wstring &wsNameFirst, const std::wstring &wsNameSecond) { if(!wsNameFirst.empty()) pXmlWriter->WriteString(wsNameFirst + L" "); else if(m_pFirstValue != nullptr) m_pFirstValue->ConversionOOXml(pXmlWriter); else pXmlWriter->WriteString(L"0 "); if(!wsNameSecond.empty()) pXmlWriter->WriteString(wsNameSecond + L" "); else if(m_pSecondValue != nullptr) m_pSecondValue->ConversionOOXml(pXmlWriter); else if(m_enTypeSign == TypeElement::minus || m_pSecondSign != nullptr) pXmlWriter->WriteString(L"0 "); else pXmlWriter->WriteString(L"1 "); } //CSMReader CSMReader::CSMReader(const std::wstring& wsFormula, const std::wstring &wsLeft, const std::wstring &wsTop, const std::wstring &wsRight, const std::wstring &wsBottom) : m_Formula (wsFormula), m_pElement(nullptr), m_bDoubleSign(false),m_wsLeft(wsLeft),m_wsTop(wsTop),m_wsRight(wsRight),m_wsBottom(wsBottom) { m_itStart = m_Formula.begin(); m_itEnd = m_Formula.end(); } CSMReader::~CSMReader() { delete m_pElement; } std::wstring CSMReader::GetElement(std::wstring::iterator& itStart,std::wstring::iterator& itEnd) { std::wstring wsOneElement{L""}; for(;itStart != itEnd;itStart++) { if(iswspace(*itStart)) { if(!wsOneElement.empty()) return wsOneElement; else continue; } else if(!wsOneElement.empty() && wsOneElement.back() == L'-') { if(L'-' == *itStart) { wsOneElement.push_back(*itStart); itStart++; return wsOneElement; } else return wsOneElement; } else if(!wsOneElement.empty() && (L'+' == *itStart || L'*' == *itStart || L'/' == *itStart || L',' == *itStart || L'(' == *itStart || L')' == *itStart || L'-' == *itStart)) return wsOneElement; else if(wsOneElement.empty() && (L'+' == *itStart || L'*' == *itStart || L'/' == *itStart || L',' == *itStart || L'(' == *itStart || L')' == *itStart)) { wsOneElement.push_back(*itStart); itStart++; return wsOneElement; } else wsOneElement.push_back(*itStart); } if(!wsOneElement.empty()) return wsOneElement; else return L""; } CElement *CSMReader::ReadingElement() { std::wstring wsElement = GetElement(m_itStart,m_itEnd); return CElement::CreateElement(wsElement); } bool CSMReader::ReadingNextElement() { if(!m_wsElement.empty()) return true; m_wsElement = GetElement(m_itStart,m_itEnd); if(!m_wsElement.empty()) return true; else return false; } bool CSMReader::CheckIteratorPosition() { if(m_itStart == m_itEnd) return true; else return false; } std::wstring CSMReader::GetElement() { return m_wsElement; } void CSMReader::ClearElement() { m_wsElement.clear(); } void CSMReader::FindingTheEndOfTheBrackets() { std::wstring::iterator itStartTemp = m_itStart; unsigned int uiOpenBracket{0}; for(;m_itStart !=m_itEnd;m_itStart++) { if(*m_itStart == L')' && uiOpenBracket == 0) { // m_itEndForBrecket = m_itEnd; m_stEndBrecket.push(m_itEnd); m_itEnd = m_itStart; m_itStart = itStartTemp; if(m_wsElement == L"(") m_wsElement.clear(); return; } else if(*m_itStart == L')' && uiOpenBracket != 0) { // m_stEndBrecket.push(m_itStart); uiOpenBracket--; } else if(*m_itStart == L'(') uiOpenBracket++; } } void CSMReader::RemovingTheParenthesisIterator() { if(!m_stEndBrecket.empty()) { m_itEnd = m_stEndBrecket.top(); m_stEndBrecket.pop(); } m_wsElement = GetElement(m_itStart,m_itEnd); m_wsElement.clear(); } void CSMReader::SetDoubleSign(const bool& bDoubleSign) { m_bDoubleSign = bDoubleSign; } bool CSMReader::GetDoubleSign() { return m_bDoubleSign; } std::wstring CSMReader::GetLeft() { return m_wsLeft; } std::wstring CSMReader::GetTop() { return m_wsTop; } std::wstring CSMReader::GetRight() { return m_wsRight; } std::wstring CSMReader::GetBottom() { return m_wsBottom; } //CElementBracket CElementBracket::CElementBracket() { SetBaseType(TypeElement::Bracket); } CElementBracket::~CElementBracket() { for(CElement* pElement:m_arElements) delete pElement; } void CElementBracket::Parse(CSMReader* pReader) { pReader->FindingTheEndOfTheBrackets(); SMCustomShapePars::ParsString(pReader,m_arElements); pReader->RemovingTheParenthesisIterator(); } void CElementBracket::ConversionOOXml(XmlUtils::CXmlWriter* pXmlWriter, const std::wstring &wsName) { if(!wsName.empty()) SetNameFormula(wsName); for(CElement* pElement:m_arElements) { if(pElement != nullptr) pElement->ConversionOOXml(pXmlWriter,wsName); } } std::vector CElementBracket::GetVector() { return m_arElements; } //CElementFunction CElementFunction::CElementFunction():m_enTypeFunction(TypeElement::empty),m_pValue(nullptr),m_uiNumberFormula(1) { SetBaseType(TypeElement::Function); } CElementFunction::CElementFunction(const TypeElement& enType):m_pValue(nullptr),m_uiNumberFormula(1) { SetBaseType(TypeElement::Function); m_enTypeFunction = enType; } CElementFunction::~CElementFunction() {} TypeElement CElementFunction::TypeCheckingByFunction(const std::wstring& wsFunction) { if(wsFunction == L"sqrt") return TypeElement::sqrt; else if(wsFunction == L"sin") return TypeElement::sin; else if(wsFunction == L"cos") return TypeElement::cos; else if(wsFunction == L"abs") return TypeElement::abs; else if(wsFunction == L"if") return TypeElement::If; else if(wsFunction == L"tan") return TypeElement::tan; else if(wsFunction == L"min") return TypeElement::min; else if(wsFunction == L"max") return TypeElement::max; else if(wsFunction == L"atan") return TypeElement::atan; else if(wsFunction == L"atan2") return TypeElement::atan2; else if(wsFunction == L"logheight") return TypeElement::logheight; else if(wsFunction == L"logwidth") return TypeElement::logwidth; else if(wsFunction == L"pi") return TypeElement::pi; else return TypeElement::empty; } void CElementFunction::Parse(CSMReader* pReader) { pReader->ClearElement(); if(m_enTypeFunction != TypeElement::logheight && m_enTypeFunction != TypeElement::logwidth && m_enTypeFunction != TypeElement::pi) m_pValue = SMCustomShapePars::ParseElement(pReader); } void CElementFunction::ConversionOOXml(XmlUtils::CXmlWriter* pXmlWriter, const std::wstring &wsName) { if(m_pValue == nullptr && m_enTypeFunction != TypeElement::logheight && m_enTypeFunction != TypeElement::logwidth && m_enTypeFunction != TypeElement::pi) { if(!wsName.empty()) SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,wsName,L"sqrt 0 "); else SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,L"gdTemp",L"sqrt 0 "); return; } if(!wsName.empty()) SetNameFormula(wsName); else SetNameFormula(L"Function"); switch (m_enTypeFunction) { case TypeElement::If: { std::wstring wsFormula = L"?: "; if(m_pValue->GetBaseType() == TypeElement::Bracket) { CElementBracket* pBracket = dynamic_cast(m_pValue); std::vector arVector = pBracket->GetVector(); if(!arVector.empty()) for(unsigned int i = 0; i < arVector.size(); i++) { if(arVector[i]->GetBaseType() == TypeElement::comma) { if(i - 1 >= 0) { ConversionElement(pXmlWriter,arVector[i - 1],wsFormula); } else wsFormula += L"1 "; } else if(i + 1 == arVector.size() && arVector[i]->GetBaseType() != TypeElement::comma) ConversionElement(pXmlWriter,arVector[i],wsFormula); } else wsFormula += L"0 0 0 "; } SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),wsFormula); break; } case TypeElement::abs: case TypeElement::sqrt: { std::wstring wsFormula; if(m_enTypeFunction == TypeElement::abs) wsFormula = L"abs "; else wsFormula = L"sqrt "; if(m_pValue->GetBaseType() == TypeElement::Bracket) { CElementBracket* pBracket = dynamic_cast(m_pValue); std::vector arValues = pBracket->GetVector(); if(!arValues.empty()) ConversionElement(pXmlWriter,arValues[0],wsFormula); else wsFormula += L"0 "; } else ConversionElement(pXmlWriter,m_pValue,wsFormula); SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),wsFormula); break; } case TypeElement::min: case TypeElement::max: { std::wstring wsFormula; if(m_enTypeFunction == TypeElement::max) wsFormula = L"max "; else wsFormula = L"min "; if(m_pValue->GetBaseType() == TypeElement::Bracket) { CElementBracket* pBracket = dynamic_cast(m_pValue); std::vector arElements = pBracket->GetVector(); if(!arElements.empty()) for(unsigned int i = 0; i < arElements.size();i++) { if(arElements[i]->GetBaseType() == TypeElement::comma) { if(i - 1 >= 0) ConversionElement(pXmlWriter,arElements[i-1],wsFormula); if(i + 1 <= arElements.size() && arElements[i+1]->GetBaseType() != TypeElement::comma) ConversionElement(pXmlWriter,arElements[i+1],wsFormula); i = arElements.size(); } } else wsFormula += L"0 0 "; SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),wsFormula); } break; } case TypeElement::sin: case TypeElement::cos: case TypeElement::atan: case TypeElement::atan2: case TypeElement::tan: { std::wstring wsFormula; if(m_enTypeFunction == TypeElement::sin) wsFormula = L"sin"; else if(m_enTypeFunction == TypeElement::cos) wsFormula = L"cos"; else if(m_enTypeFunction == TypeElement::tan) wsFormula = L"tan"; else if(m_enTypeFunction == TypeElement::atan || m_enTypeFunction == TypeElement::atan2) wsFormula = L"at2 "; if(m_enTypeFunction != TypeElement::atan2) wsFormula += L" 1 "; if(!ConvertBracketsForTrigonometry(pXmlWriter,wsFormula,m_enTypeFunction)) { if(m_enTypeFunction != TypeElement::atan2) wsFormula += L"0 "; else wsFormula += L" 0 0 "; } SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),wsFormula); break; } case TypeElement::logheight: case TypeElement::logwidth: { CalculatingTheLogicalHeightOrWidth(pXmlWriter); break; } case TypeElement::pi: { SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),L"+/ 0 355 113"); } default: break; } } void CElementFunction::CalculatingTheLogicalHeightOrWidth(XmlUtils::CXmlWriter* pXmlWriter) { SMCustomShapeConversion::WritingFormulaXml(pXmlWriter,GetNameFormula(),L"*/ " + std::wstring((m_enTypeFunction == TypeElement::logheight) ? L"h":L"w") + L" 25 48 "); } void CElementFunction::CalculatingNumberName(std::wstring &wsNewName, std::wstring& wsOldNameFormula, unsigned int &uiNumberFormula) { wsNewName = wsOldNameFormula + L"." + std::to_wstring(uiNumberFormula); uiNumberFormula++; } void CElementFunction::ConversionElement(XmlUtils::CXmlWriter* pXmlWriter, CElement *pElement, std::wstring &wsFormula) { if(pElement == nullptr) return; if(pElement->GetBaseType() == TypeElement::NumberOrName) { CElementNumber* pTempElement = dynamic_cast(pElement); wsFormula += pTempElement->GetString() + L" "; } else { std::wstring wsNewName,wsOldName = GetNameFormula(); CElementFunction::CalculatingNumberName(wsNewName,wsOldName,m_uiNumberFormula); wsFormula += wsNewName + L" "; pElement->ConversionOOXml(pXmlWriter,wsNewName); } } bool CElementFunction::ConvertBracketsForTrigonometry(XmlUtils::CXmlWriter* pXmlWriter, std::wstring& wsFormula, const TypeElement &enTypeFunc) { if(m_pValue->GetBaseType() == TypeElement::Bracket) { CElementBracket* pBracket = dynamic_cast(m_pValue); std::vector arVec = pBracket->GetVector(); if(arVec.empty()) return false; else for(unsigned int i = 0 ; i < arVec.size();i++) { if(arVec[i] != nullptr && arVec[i]->GetBaseType() != TypeElement::comma) ConversionElement(pXmlWriter,arVec[0],wsFormula); else wsFormula += L"0 "; if((enTypeFunc != TypeElement::atan2 && i == 0) || (enTypeFunc == TypeElement::atan2 && i == 1)) return true; } } else if(m_pValue != nullptr && m_pValue->GetBaseType() != TypeElement::comma) { ConversionElement(pXmlWriter,m_pValue,wsFormula); return true; } return false; } //CElementComma CElementComma::CElementComma() {SetBaseType(TypeElement::comma);} CElementComma::~CElementComma() {} void CElementComma::Parse(CSMReader* pReader) { if(!pReader->GetElement().empty()) pReader->ClearElement(); } void CElementComma::ConversionOOXml(XmlUtils::CXmlWriter* pXmlWriter, const std::wstring &wsName) {} //SMCustomShapeConversion SMCustomShapeConversion::SMCustomShapeConversion():m_pXmlWriter(nullptr) {} SMCustomShapeConversion::~SMCustomShapeConversion() { delete m_pXmlWriter; } void SMCustomShapeConversion::StartConversion(std::vector& arElements, const std::wstring& wsFormulaName) { if(arElements.empty()) return; m_pXmlWriter = new XmlUtils::CXmlWriter; if(arElements.size() == 1 && arElements[0]->GetBaseType() == TypeElement::NumberOrName) { m_pXmlWriter->WriteNodeBegin(L"a:gd",true); if(!wsFormulaName.empty()) m_pXmlWriter->WriteAttribute(L"name",wsFormulaName); else m_pXmlWriter->WriteAttribute(L"name",L"Text"); m_pXmlWriter->WriteString(L" fmla=\"val "); arElements[0]->ConversionOOXml(m_pXmlWriter,wsFormulaName); m_pXmlWriter->WriteString(L"\""); m_pXmlWriter->WriteNodeEnd(L"",true,true); } else { for(CElement* pElement:arElements) { if(pElement != nullptr) pElement->ConversionOOXml(m_pXmlWriter,wsFormulaName); } } } std::wstring SMCustomShapeConversion::GetStringXml() { return m_pXmlWriter->GetXmlString(); } void SMCustomShapeConversion::WritingFormulaXml(XmlUtils::CXmlWriter* pXmlWriter,const std::wstring& wsNameFormula,const std::wstring& wsFormula) { pXmlWriter->WriteNodeBegin(L"a:gd",true); pXmlWriter->WriteAttribute(L"name",wsNameFormula); pXmlWriter->WriteAttribute(L"fmla",wsFormula); pXmlWriter->WriteNodeEnd(L"",true,true); } std::wstring SMCustomShapeConversion::ParsFormulaName(const std::wstring& wsFormulaName, std::wstring &wsName) { if(wsFormulaName.empty()) return L""; std::wstring wsTempNumber; for(wchar_t wcElement: wsFormulaName) { if(iswdigit(wcElement) && (L'-' == wcElement || L'.' == wcElement)) wsTempNumber += wcElement; else wsName += wcElement; } if(!wsTempNumber.empty()) return wsTempNumber; else return L""; } }