Files
core/DesktopEditor/raster/Metafile/svg/CSvgFile.cpp
2024-06-25 15:51:04 +03:00

243 lines
6.3 KiB
C++

#include "CSvgFile.h"
#include "SvgObjects/CContainer.h"
#include "SvgObjects/CFont.h"
#define SVG_FILE_WIDTH 300
#define SVG_FILE_HEIGHT 150
CSvgFile::CSvgFile()
: m_oContainer(L"svg")
{}
CSvgFile::~CSvgFile()
{
Clear();
}
bool CSvgFile::ReadFromBuffer(BYTE *pBuffer, unsigned int unSize)
{
Clear();
return false;
}
bool CSvgFile::ReadFromWString(const std::wstring &wsContext)
{
Clear();
return m_oParser.LoadFromString(wsContext, &m_oContainer, this);
}
bool CSvgFile::OpenFromFile(const std::wstring &wsFile)
{
Clear();
m_wsWorkingDirectory = NSFile::GetDirectoryName(wsFile);
return m_oParser.LoadFromFile(wsFile, &m_oContainer, this);
}
bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight) const
{
if (m_oContainer.Empty())
return false;
SVG::TRect oWindow = m_oContainer.GetWindow();
dX = oWindow.m_oX.ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
dY = oWindow.m_oY.ToDouble(NSCSS::Pixel, SVG_FILE_HEIGHT);
dWidth = 0.;
dHeight = 0.;
if (!oWindow.m_oWidth.Empty() && !oWindow.m_oWidth.Zero())
{
if (NSCSS::Percent == oWindow.m_oWidth.GetUnitMeasure())
{
if (!m_oContainer.GetViewBox().m_oWidth.Empty() && !m_oContainer.GetViewBox().m_oWidth.Zero())
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, m_oContainer.GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel));
else
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
}
else
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel);
}
else
dWidth = m_oContainer.GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel);
if (!oWindow.m_oHeight.Empty() && !oWindow.m_oHeight.Zero())
{
if (NSCSS::Percent == oWindow.m_oHeight.GetUnitMeasure())
{
if (!m_oContainer.GetViewBox().m_oHeight.Empty() && !m_oContainer.GetViewBox().m_oHeight.Zero())
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel));
else
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
}
else
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel);
}
else
dHeight = m_oContainer.GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel);
if (0. == dWidth)
dWidth = SVG_FILE_WIDTH;
if (0. == dHeight)
dHeight = SVG_FILE_HEIGHT;
return true;
}
const SVG::CSvgCalculator *CSvgFile::GetSvgCalculator() const
{
return &m_oSvgCalculator;
}
void CSvgFile::SetFontManager(NSFonts::IFontManager *pFontManager)
{
m_oParser.SetFontManager(pFontManager);
}
void CSvgFile::SetWorkingDirectory(const std::wstring &wsWorkingDirectory)
{
m_wsWorkingDirectory = wsWorkingDirectory;
}
bool CSvgFile::MarkObject(SVG::CObject *pObject)
{
if (NULL == pObject || pObject->GetId().empty())
return false;
pObject->AddRef();
m_mMarkedObjects[pObject->GetId()] = pObject;
return true;
}
SVG::CObject *CSvgFile::GetMarkedObject(const std::wstring &wsId) const
{
if (wsId.empty() || m_mMarkedObjects.empty())
return NULL;
std::wstring wsNewId = wsId;
size_t unFound = wsNewId.find(L'#');
if (std::wstring::npos != unFound)
wsNewId.erase(0, unFound + 1);
MarkedMap::const_iterator oConstIter = m_mMarkedObjects.find(wsNewId);
if (m_mMarkedObjects.end() != oConstIter)
return oConstIter->second;
return NULL;
}
SVG::CFont *CSvgFile::GetFont(const std::wstring &wsFontFamily) const
{
FontsFaceMap::const_iterator itFound = std::find_if(m_mFontsFace.cbegin(), m_mFontsFace.cend(), [&wsFontFamily](const std::pair<std::wstring, std::wstring>& oValue){ return wsFontFamily == oValue.first; });
if (m_mFontsFace.cend() == itFound)
return NULL;
return dynamic_cast<SVG::CFont*>(GetMarkedObject(itFound->second));
}
std::wstring CSvgFile::GetWorkingDirectory() const
{
return m_wsWorkingDirectory;
}
void CSvgFile::AddStyles(const std::wstring &wsStyles)
{
m_oSvgCalculator.AddStyles(wsStyles);
}
void CSvgFile::AddFontFace(const SVG::TFontArguments& oArguments, const std::wstring &wsId)
{
m_mFontsFace.insert(std::make_pair(oArguments.m_wsFontFamily, wsId));
}
bool CSvgFile::Draw(IRenderer *pRenderer, double dX, double dY, double dWidth, double dHeight)
{
if (NULL == pRenderer || m_oContainer.Empty())
return false;
SVG::TRect oWindow = m_oContainer.GetWindow();
SVG::TRect oViewBox = m_oContainer.GetViewBox();
if (oWindow.m_oWidth.Empty() || oWindow.m_oWidth.Zero())
{
if (oViewBox.m_oWidth.Empty() || oViewBox.m_oWidth.Zero())
oWindow.m_oWidth = SVG_FILE_WIDTH;
else
{
oWindow.m_oWidth = oViewBox.m_oWidth;
oViewBox.m_oWidth.Clear();
}
}
if (oWindow.m_oHeight.Empty() || oWindow.m_oHeight.Zero())
{
if (oViewBox.m_oHeight.Empty() || oViewBox.m_oHeight.Zero())
oWindow.m_oHeight = SVG_FILE_HEIGHT;
else
{
oWindow.m_oHeight = oViewBox.m_oHeight;
oViewBox.m_oHeight.Clear();
}
}
double dViewBoxWidth = oViewBox.m_oWidth.ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH);
double dViewBoxHeight = oViewBox.m_oHeight.ToDouble(NSCSS::Pixel, SVG_FILE_HEIGHT);
double dWindowWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, dViewBoxWidth);
double dWindowHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, dViewBoxHeight);
if (SVG::Equals(0., dWindowWidth) || SVG::Equals(0., dWindowHeight))
return false;
double oldTransform[6];
oldTransform[0] = oldTransform[3] = 1;
oldTransform[1] = oldTransform[2] = oldTransform[4] = oldTransform[5] = 0;
pRenderer->GetTransform(&oldTransform[0], &oldTransform[1], &oldTransform[2], &oldTransform[3], &oldTransform[4], &oldTransform[5]);
pRenderer->ResetTransform();
double dM11 = dWidth / dWindowWidth;
double dM22 = dHeight / dWindowHeight;
double dScaleX = 1, dScaleY = 1;
if (!SVG::Equals(0., dViewBoxWidth))
dScaleX = dWindowWidth / dViewBoxWidth;
if (!SVG::Equals(0., dViewBoxHeight))
dScaleY = dWindowHeight / dViewBoxHeight;
double dMinScale = std::min(dScaleX, dScaleY);
double dSkipX = -oViewBox.m_oX.ToDouble(NSCSS::Pixel) * dScaleX * dM11;
double dSkipY = -oViewBox.m_oY.ToDouble(NSCSS::Pixel) * dScaleY * dM22;
pRenderer->SetTransform(dM11 * dMinScale, 0, 0, dM22 * dMinScale, dSkipX, dSkipY);
bool bResult = m_oContainer.Draw(pRenderer, this);
pRenderer->SetTransform(oldTransform[0], oldTransform[1], oldTransform[2], oldTransform[3], oldTransform[4], oldTransform[5]);
return bResult;
}
void CSvgFile::Clear()
{
m_oContainer.Clear();
m_oSvgCalculator.Clear();
for (MarkedMap::reference oIter : m_mMarkedObjects)
RELEASEINTERFACE(oIter.second);
m_mMarkedObjects.clear();
m_wsWorkingDirectory.clear();
}