Files
core/DesktopEditor/raster/Metafile/svg/SvgReader.cpp
2025-10-14 20:42:24 +03:00

354 lines
6.7 KiB
C++

#include "SvgReader.h"
#include <cmath>
#include <cctype>
namespace SVG
{
int ConvertHexToInt(const std::string& sValue, const int& _default)
{
if (sValue.empty() || "none" == sValue)
return _default;
std::string::const_iterator itStart = sValue.cbegin();
if ('#' == *itStart)
++itStart;
if (sValue.cend() - itStart != 6)
return _default;
itStart = sValue.cend() - 6;
int nResult = 0;
while (itStart != sValue.cend())
{
if ('0' <= *itStart && *itStart <= '9')
nResult = (nResult << 4) | (*itStart++ - '0');
else if ('A' <= *itStart && *itStart <= 'F')
nResult = (nResult << 4) | (*itStart++ - 'A' + 10);
else if ('a' <= *itStart && *itStart <= 'f')
nResult = (nResult << 4) | (*itStart++ - 'a' + 10);
else
return _default;
}
return nResult;
}
CSvgReader::CSvgReader()
: m_pReader(new XmlUtils::CXmlLiteReader), m_bParseAttribute(false)
{}
CSvgReader::~CSvgReader()
{
if (nullptr != m_pReader)
delete m_pReader;
}
bool SVG::CSvgReader::ReadFromFile(const std::wstring& wsFilePath)
{
return (nullptr != m_pReader) ? m_pReader->FromFile(wsFilePath) : false;
}
bool SVG::CSvgReader::ReadFromString(const std::wstring& wsSvg)
{
if (nullptr != m_pReader && m_pReader->FromString(wsSvg))
return m_pReader->ReadNextNode();
return false;
}
// XmlUtils::CXmlLiteReader* CSvgReader::GetReader()
// {
// return m_pReader;
// }
unsigned int CSvgReader::GetDepth()
{
return (nullptr != m_pReader) ? m_pReader->GetDepth() : 0;
}
bool CSvgReader::IsEmptyNode()
{
return (nullptr != m_pReader) ? m_pReader->IsEmptyNode() : true;
}
bool CSvgReader::GetBool()
{
return "1" == GetTextAValue(*this) || "true" == GetTextAValue(*this);
}
int StringToInt(const std::string& sValue, const int& _default)
{
std::string::const_iterator itPos{sValue.cbegin()};
while (std::isspace(*itPos))
++itPos;
if (sValue.cend() == itPos)
return _default;
while (sValue.cend() != itPos && !std::isdigit(*itPos))
++itPos;
if (sValue.cend() == itPos)
return _default;
int nResult = 0;
while (itPos != sValue.cend() && std::isdigit(*itPos))
{
nResult = nResult * 10 + (*itPos - '0');
++itPos;
}
return ((nResult & 0xFF) << 16) | (((nResult >> 8) & 0xFF) << 8) | ((nResult >> 16) & 0xFF);
}
int CSvgReader::GetColor(const int& nDefault)
{
const std::string sValue{GetTextAValue(*this)};
if (sValue.empty())
return nDefault;
if ('#' == sValue[0])
return ConvertHexToInt(sValue, nDefault);
return StringToInt(sValue, nDefault);
}
int CSvgReader::GetInt()
{
return GetIntValue(*this);
}
double CSvgReader::GetDouble()
{
return GetDoubleValue(*this);
}
std::string CSvgReader::GetTextA()
{
if (nullptr == m_pReader)
return std::string();
return (m_bParseAttribute) ? m_pReader->GetTextA() : m_pReader->GetText2A();
}
std::wstring CSvgReader::GetText()
{
if (nullptr == m_pReader)
return std::wstring();
return (m_bParseAttribute) ? m_pReader->GetText() : m_pReader->GetText2();
}
const char* CSvgReader::GetTextChar()
{
if (nullptr == m_pReader)
return "";
return m_pReader->GetTextChar();
}
template<typename T>
T CSvgReader::GetAttribute(const std::string& sName, T _default, T (*GetValue)(CSvgReader&))
{
if (!MoveToFirstAttribute())
return _default;
T oValue = _default;
do
{
if (sName == m_pReader->GetNameA())
{
oValue = GetValue(*this);
break;
}
}while(m_pReader->MoveToNextAttribute());
MoveToElement();
return oValue;
}
int CSvgReader::GetAttributeInt(const std::string& sName, int nDefault)
{
return GetAttribute<int>(sName, nDefault, &GetIntValue);
}
bool CSvgReader::GetAttributeBool(const std::string& sName)
{
return GetAttribute<bool>(sName, false, &GetBoolValue);
}
double CSvgReader::GetAttributeDouble(const std::string& sName)
{
return GetAttribute<double>(sName, 0., &GetDoubleValue);
}
std::string CSvgReader::GetAttributeA(const std::string& sName)
{
return GetAttribute<std::string>(sName, "", &GetTextAValue);
}
std::wstring CSvgReader::GetAttribute(const std::string& sName)
{
return GetAttribute<std::wstring>(sName, L"", &GetTextValue);
}
bool CSvgReader::MoveToStart()
{
if (nullptr != m_pReader && m_pReader->MoveToStart())
return m_pReader->ReadNextNode();
return false;
}
bool CSvgReader::MoveToFirstAttribute()
{
if (nullptr == m_pReader || !m_pReader->MoveToFirstAttribute())
return false;
m_bParseAttribute = true;
return true;
}
bool CSvgReader::MoveToNextAttribute()
{
return (nullptr != m_pReader) ? m_pReader->MoveToNextAttribute() : false;
}
bool CSvgReader::MoveToElement()
{
if (nullptr == m_pReader || !m_pReader->MoveToElement())
return false;
m_bParseAttribute = false;
return true;
}
std::string CSvgReader::GetName()
{
return (nullptr != m_pReader) ? m_pReader->GetNameA() : std::string();
}
std::wstring CSvgReader::GetNameW()
{
return (nullptr != m_pReader) ? m_pReader->GetName() : std::wstring();
}
bool CSvgReader::ReadNextSiblingNode(unsigned int unDepth)
{
return (nullptr != m_pReader) ? m_pReader->ReadNextSiblingNode(unDepth) : false;
}
bool CSvgReader::ReadNextNode()
{
return (nullptr != m_pReader) ? m_pReader->ReadNextNode() : false;
}
bool CSvgReader::Read(XmlUtils::XmlNodeType& eNodeType)
{
return (nullptr != m_pReader) ? m_pReader->Read(eNodeType) : false;
}
int CSvgReader::GetIntValue(CSvgReader& oXmlReader)
{
return std::atoi(oXmlReader.GetTextA().c_str());
}
bool CSvgReader::GetBoolValue(CSvgReader& oXmlReader)
{
return "1" == oXmlReader.GetTextA();
}
double CSvgReader::GetDoubleValue(CSvgReader& oXmlReader)
{
const std::string sValue{oXmlReader.GetTextA()};
const char* pCur = sValue.c_str();
while (std::isspace(*pCur))
++pCur;
if (!pCur)
return 0.;
bool bNegative = false;
while ('-' == *pCur || '+' == *pCur)
{
if ('-' == *pCur)
bNegative = !bNegative;
++pCur;
}
if (!pCur)
return 0.;
double dResult = 0.;
while (std::isdigit(*pCur))
dResult = dResult * 10. + (*pCur++ - '0');
if (',' == *pCur || '.' == *pCur)
{
++pCur;
double dFraction = 0.0;
double dDivisor = 1.0;
while (std::isdigit(*pCur))
{
dFraction = dFraction * 10. + (*pCur++ - '0');
dDivisor *= 10;
}
dResult += dFraction / dDivisor;
}
if ('e' == *pCur || 'E' == *pCur)
{
++pCur;
bool bExpNegative = false;
while ('-' == *pCur || '+' == *pCur)
{
if ('-' == *pCur)
bExpNegative = !bExpNegative;
++pCur;
}
int nExponent = 0;
while (std::isdigit(*pCur))
nExponent = nExponent * 10 + (*pCur++ - '0');
if (bExpNegative)
nExponent = -nExponent;
dResult *= std::pow(10., nExponent);
}
return bNegative ? -dResult : dResult;
}
std::string CSvgReader::GetTextAValue(CSvgReader& oXmlReader)
{
return oXmlReader.GetTextA();
}
std::wstring CSvgReader::GetTextValue(CSvgReader& oXmlReader)
{
return oXmlReader.GetText();
}
}