Intermediate refactoring

This commit is contained in:
Kirill Polyakov
2025-10-15 19:06:28 +03:00
parent 6eeae2e804
commit 7156669830
33 changed files with 455 additions and 471 deletions

View File

@ -3,11 +3,13 @@
#include "SvgObjects/CContainer.h"
#include "SvgObjects/CFont.h"
#include "CSvgParser.h"
#define SVG_FILE_WIDTH 300
#define SVG_FILE_HEIGHT 150
CSvgFile::CSvgFile()
: m_pContainer(NULL)
: m_pContainer(NULL), m_pFontManager(NULL)
{}
CSvgFile::~CSvgFile()
@ -24,7 +26,10 @@ bool CSvgFile::ReadFromBuffer(BYTE *pBuffer, unsigned int unSize)
bool CSvgFile::ReadFromWString(const std::wstring &wsContext)
{
Clear();
return m_oParser.LoadFromString(wsContext, m_pContainer, this);
SVG::CSvgParser oSvgParser(m_pFontManager);
return oSvgParser.LoadFromString(wsContext, m_pContainer, this);
}
bool CSvgFile::OpenFromFile(const std::wstring &wsFile)
@ -33,7 +38,9 @@ bool CSvgFile::OpenFromFile(const std::wstring &wsFile)
m_wsWorkingDirectory = NSFile::GetDirectoryName(wsFile);
return m_oParser.LoadFromFile(wsFile, m_pContainer, this);
SVG::CSvgParser oSvgParser(m_pFontManager);
return oSvgParser.LoadFromFile(wsFile, m_pContainer, this);
}
bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight) const
@ -94,7 +101,7 @@ const SVG::CSvgCalculator *CSvgFile::GetSvgCalculator() const
void CSvgFile::SetFontManager(NSFonts::IFontManager *pFontManager)
{
m_oParser.SetFontManager(pFontManager);
m_pFontManager = pFontManager;
}
void CSvgFile::SetWorkingDirectory(const std::wstring &wsWorkingDirectory)

View File

@ -4,13 +4,13 @@
#include "../../../graphics/IRenderer.h"
#include "../../../graphics/pro/Fonts.h"
#include "CSvgParser.h"
#include "SvgObjects/CStyle.h"
namespace SVG
{
struct TFontArguments;
class CFont;
class CGraphicsContainer;
}
class CSvgFile
@ -43,9 +43,9 @@ class CSvgFile
private:
void Clear();
SVG::CSvgParser m_oParser;
SVG::CGraphicsContainer *m_pContainer;
SVG::CSvgCalculator m_oSvgCalculator;
NSFonts::IFontManager *m_pFontManager;
typedef std::map<std::wstring, SVG::CObject*> MarkedMap;

View File

@ -28,14 +28,12 @@
namespace SVG
{
CSvgParser::CSvgParser()
: m_pFontManager(NULL)
{
}
CSvgParser::CSvgParser(NSFonts::IFontManager* pFontManager)
: m_pFontManager(pFontManager)
{}
CSvgParser::~CSvgParser()
{
}
{}
void CSvgParser::SetFontManager(NSFonts::IFontManager *pFontManager)
{
@ -104,11 +102,7 @@ namespace SVG
else
return false;
XmlUtils::IXmlDOMDocument::DisableOutput();
bool bResult = LoadFromString(wsContent, pContainer, pFile);
XmlUtils::IXmlDOMDocument::EnableOutput();
return bResult;
return LoadFromString(wsContent, pContainer, pFile);
}
bool CSvgParser::LoadFromString(const std::wstring &wsContent, CGraphicsContainer*& pContainer, CSvgFile* pFile) const
@ -125,12 +119,11 @@ namespace SVG
RELEASEOBJECT(pContainer);
pContainer = CRenderedObject::Create<CGraphicsContainer>(oReader, pFile->GetSvgCalculator());
pContainer = CObject::Create<CGraphicsContainer>(oReader, pFile);
if (NULL == pContainer)
return false;
return ReadChildrens(oReader, pContainer, pFile, pContainer);
}
@ -216,22 +209,6 @@ namespace SVG
oSearchStart = oMatch.suffix().first;
}
}
template <class TextType>
TextType* ReadTextObject(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator, CRenderedObject *pParent, NSFonts::IFontManager* pFontManager)
{
//1 - создаем родительский объект
//2 - парсим аргументы
//3 - SetData
//4 - чтение дочерних (текста и внутри)
TextType *pText = CRenderedObject::Create<TextType>(oReader, pSvgCalculator, pParent, pFontManager);
if (NULL == pText)
return NULL;
return pText;
}
template <class ObjectType>
bool CSvgParser::ReadObject(CSvgReader& oReader, CContainer<ObjectType> *pContainer, CSvgFile *pFile, CRenderedObject *pParent) const
{
@ -244,7 +221,7 @@ namespace SVG
if ("svg" == sElementName || "g" == sElementName || "a" == sElementName)
{
pObject = CRenderedObject::Create<CGraphicsContainer>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CGraphicsContainer>(oReader, pFile, pParent);
if (!ReadChildrens(oReader, (CGraphicsContainer*)pObject, pFile, (CGraphicsContainer*)pObject))
{
RELEASEOBJECT(pObject);
@ -252,138 +229,83 @@ namespace SVG
}
}
else if ("line" == sElementName)
pObject = CRenderedObject::Create<CLine>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CLine>(oReader, pFile, pParent);
else if ("rect" == sElementName)
pObject = CRenderedObject::Create<CRect>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CRect>(oReader, pFile, pParent);
else if ("circle" == sElementName)
pObject = CRenderedObject::Create<CCircle>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CCircle>(oReader, pFile, pParent);
else if ("ellipse" == sElementName)
pObject = CRenderedObject::Create<CEllipse>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CEllipse>(oReader, pFile, pParent);
else if ("path" == sElementName)
pObject = CRenderedObject::Create<CPath>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CPath>(oReader, pFile, pParent);
else if ("polyline" == sElementName)
pObject = CRenderedObject::Create<CPolyline>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CPolyline>(oReader, pFile, pParent);
else if ("polygon" == sElementName)
pObject = CRenderedObject::Create<CPolygon>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CPolygon>(oReader, pFile, pParent);
else if ("image" == sElementName)
pObject = CRenderedObject::Create<CImage>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CImage>(oReader, pFile, pParent);
else if ("use" == sElementName)
pObject = CRenderedObject::Create<CUse>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CUse>(oReader, pFile, pParent);
else if ("text" == sElementName)
{
pObject = ReadTextObject<CText>(oReader, pFile->GetSvgCalculator(), pParent, m_pFontManager);
// pObject = CText::Create(oReader, pParent, m_pFontManager);
// ReadChildrens(oReader, (CText*)pObject, pFile, (CText*)pObject);
}
pObject = CObject::Create<CText>(oReader, pFile, pParent, m_pFontManager);
else if ("tspan" == sElementName)
{
pObject = ReadTextObject<CTSpan>(oReader, pFile->GetSvgCalculator(), pParent, m_pFontManager);
// pObject = CTSpan::Create(oReader, pParent, m_pFontManager);
// ReadChildrens(oReader, (CTSpan*)pObject, pFile, (CTSpan*)pObject);
}
pObject = CObject::Create<CTSpan>(oReader, pFile, pParent, m_pFontManager);
else if ("textPath" == sElementName)
{
pObject = ReadTextObject<CTextPath>(oReader, pFile->GetSvgCalculator(), pParent, m_pFontManager);
// pObject = CTextPath::Create(oReader, pParent, m_pFontManager);
// ReadChildrens(oReader, (CTextPath*)pObject, pFile);
}
pObject = CObject::Create<CTextPath>(oReader, pFile, pParent, m_pFontManager);
else if ("switch" == sElementName)
{
pObject = CRenderedObject::Create<CSwitch>(oReader, pFile->GetSvgCalculator(), pParent);
pObject = CObject::Create<CSwitch>(oReader, pFile, pParent);
ReadChildrens(oReader, (CSwitch*)pObject, pFile);
}
//defs
else if ("defs" == sElementName)
return ReadChildrens<CRenderedObject>(oReader, NULL, pFile);
else if("linearGradient" == sElementName)
{
pObject = new CLinearGradient(oReader);
ReadChildrens(oReader, (CLinearGradient*)pObject, pFile);
}
pObject = CObject::Create<CLinearGradient>(oReader, pFile);
else if ("radialGradient" == sElementName)
{
pObject = new CRadialGradient(oReader);
ReadChildrens(oReader, (CRadialGradient*)pObject, pFile);
}
else if ("stop" == sElementName)
{
CStopElement *pStopElement = new CStopElement(oReader);
if (AddObject((ObjectType*)pStopElement, pContainer))
{
UpdateStyles(pStopElement, pFile);
return true;
}
else
{
RELEASEOBJECT(pStopElement);
return false;
}
}
pObject = CObject::Create<CRadialGradient>(oReader, pFile);
else if ("pattern" == sElementName)
{
pObject = new CPattern(oReader, m_pFontManager);
pObject = CObject::Create<CPattern>(oReader, pFile);
ReadChildrens(oReader, (CGraphicsContainer*)(&((CPattern*)pObject)->GetContainer()), pFile);
}
else if ("clipPath" == sElementName)
{
pObject = new CClipPath(oReader);
pObject = CObject::Create<CClipPath>(oReader, pFile);
ReadChildrens(oReader, (CGraphicsContainer*)(&((CClipPath*)pObject)->GetContainer()), pFile);
}
else if ("marker" == sElementName)
{
pObject = new CMarker(oReader);
pObject = CObject::Create<CMarker>(oReader, pFile);
ReadChildrens(oReader, (CMarker*)pObject, pFile);
}
else if ("mask" == sElementName)
{
pObject = new CMask(oReader);
pObject = CObject::Create<CMask>(oReader, pFile);
ReadChildrens(oReader, (CGraphicsContainer*)(&((CMask*)pObject)->GetContainer()), pFile);
}
else if ("symbo" == sElementName)
else if ("symbol" == sElementName)
{
pObject = CRenderedObject::Create<CSymbol>(oReader, pFile->GetSvgCalculator());
if (ReadChildrens(oReader, (CSymbol*)pObject, pFile) && MarkObject(pObject, pFile))
pObject = CObject::Create<CSymbol>(oReader, pFile);
if (ReadChildrens(oReader, (CSymbol*)pObject, pFile))
return true;
else
RELEASEOBJECT(pObject);
}
else if ("font" == sElementName)
{
pObject = new CFont(oReader);
pObject = CObject::Create<CFont>(oReader, pFile);
}
if (NULL != pObject)
{
if ((MarkObject(pObject, pFile) && (AppliedObject == pObject->GetType() || NULL == pContainer)) ||
(RendererObject == pObject->GetType() && AddObject((ObjectType*)pObject, pContainer)))
{
if (RendererObject != pObject->GetType())
UpdateStyles(pObject, pFile);
return true;
}
delete pObject;
}
return false;
}
void CSvgParser::UpdateStyles(CObject *pObject, CSvgFile *pFile) const
{
if (NULL == pObject || NULL == pFile)
return;
const CSvgCalculator *pSvgCalculator = pFile->GetSvgCalculator();
if (NULL != pSvgCalculator)
pSvgCalculator->SetData(pObject);
}
bool CSvgParser::MarkObject(CObject *pObject, CSvgFile *pFile) const
{
if (NULL == pObject || NULL == pFile)
if (NULL == pObject)
return false;
return pFile->MarkObject(pObject);
if ((RendererObject == pObject->GetType() && AddObject((ObjectType*)pObject, pContainer)) ||
AppliedObject == pObject->GetType())
return true;
RELEASEOBJECT(pObject);
return false;
}
template <class ObjectType>

View File

@ -14,7 +14,7 @@ namespace SVG
class CSvgParser
{
public:
CSvgParser();
CSvgParser(NSFonts::IFontManager* pFontManager = NULL);
~CSvgParser();
void SetFontManager(NSFonts::IFontManager* pFontManager);
@ -31,8 +31,6 @@ namespace SVG
bool ScanStyles(CSvgReader& oReader, CSvgFile* pFile) const;
void ParseStyles(const std::wstring& wsStyles, CSvgFile *pFile) const;
void UpdateStyles(CObject* pObject, CSvgFile* pFile) const;
bool MarkObject(CObject* pObject, CSvgFile* pFile) const;
template <class ObjectType>
bool AddObject(ObjectType* pObject, CContainer<ObjectType>* pContainer) const;

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CCircle : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
CCircle(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -31,7 +31,7 @@ namespace SVG
ApplyClip(pRenderer, &m_oTransformation.m_oClip, pFile, oObjectBounds);
for (const CRenderedObject* pObject : m_oContainer.m_arObjects)
for (const CRenderedObject* pObject : m_oContainer)
pObject->Draw(pRenderer, pFile, CommandeModeClip);
return true;

View File

@ -13,9 +13,9 @@ namespace SVG
class CClipPath : public CAppliedObject
{
public:
friend class CObject;
CClipPath(CSvgReader& oReader);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
void SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode) override;

View File

@ -5,15 +5,9 @@
namespace SVG
{
// CGraphicsContainer::CGraphicsContainer(const std::wstring &wsName)
// : CRenderedObject(NSCSS::CNode(wsName, L"", L""))
// {}
CGraphicsContainer::~CGraphicsContainer()
{
for (CRenderedObject* pObject : m_arObjects)
pObject->m_pParent = NULL;
}
CGraphicsContainer::CGraphicsContainer(CSvgReader& oReader, CRenderedObject *pParent)
: CRenderedObject(oReader, pParent)
{}
void CGraphicsContainer::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
@ -27,9 +21,7 @@ namespace SVG
m_oWindow.m_oHeight.SetValue(oReader.GetDouble());
else if ("viewBox" == sName)
{
m_oViewBox = m_oWindow;
std::vector<double> arValues = StrUtils::ReadDoubleValues(oReader.GetText());
const std::vector<double> arValues{StrUtils::ReadDoubleValues(oReader.GetText())};
if (4 == arValues.size())
{
m_oViewBox.m_oX = arValues[0];
@ -42,14 +34,6 @@ namespace SVG
CRenderedObject::SetAttribute(sName, oReader);
}
CGraphicsContainer::CGraphicsContainer(CSvgReader& oReader, CRenderedObject *pParent)
: CRenderedObject(oReader, pParent)
{}
CGraphicsContainer::CGraphicsContainer(double dWidth, double dHeight, CSvgReader& oReader, CRenderedObject *pParent)
: CRenderedObject(oReader, pParent), m_oWindow{0, 0, dWidth, dHeight}
{}
bool CGraphicsContainer::Draw(IRenderer *pRenderer, const CSvgFile *pFile, CommandeMode oMode, const TSvgStyles *pOtherStyles, const CRenderedObject* pContexObject) const
{
Aggplus::CMatrix oOldTransform;
@ -72,6 +56,9 @@ namespace SVG
TRect CGraphicsContainer::GetViewBox() const
{
if (m_oViewBox.m_oWidth.Empty() || m_oViewBox.m_oHeight.Empty())
return m_oWindow;
return m_oViewBox;
}

View File

@ -12,8 +12,9 @@ namespace SVG
template<typename TypeObject>
class CContainer
{
using const_iterator = typename std::vector<TypeObject*>::const_iterator;
public:
CContainer(){}
CContainer() = default;
virtual ~CContainer()
{
Clear();
@ -61,31 +62,26 @@ namespace SVG
return NULL;
}
private:
std::vector<TypeObject*> m_arObjects;
friend class CText;
friend class CMask;
friend class CTSpan;
friend class CMarker;
friend class CSwitch;
friend class CPattern;
friend class CGradient;
friend class CClipPath;
friend class CTextPath;
friend class CLinearGradient;
friend class CGraphicsContainer;
const_iterator begin() const
{
return m_arObjects.cbegin();
}
const_iterator end() const
{
return m_arObjects.cend();
}
protected:
std::vector<TypeObject*> m_arObjects;
};
class CGraphicsContainer : public CContainer<CRenderedObject>, public CRenderedObject
{
friend class CRenderedObject;
// CGraphicsContainer(const std::wstring& wsName = L"GraphicsContainer");
friend class CObject;
CGraphicsContainer(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
CGraphicsContainer(double dWidth, double dHeight, CSvgReader& oReader, CRenderedObject* pParent = NULL);
virtual ~CGraphicsContainer();
virtual ~CGraphicsContainer() = default;
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CEllipse : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
CEllipse(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) override;

View File

@ -36,8 +36,9 @@ namespace SVG
class CFont : public CAppliedObject
{
public:
friend class CObject;
CFont(CSvgReader& oReader);
public:
~CFont();
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -56,6 +56,25 @@ namespace SVG
void CGradient::SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode)
{}
void CGradient::ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile)
{
if (NULL == pSvgFile || NULL == pSvgFile->GetSvgCalculator())
return;
WHILE_READ_NEXT_NODE_WITH_ONE_NAME(oReader, "stop")
{
CStopElement *pStopElement = new CStopElement(oReader);
if (NULL == pStopElement)
continue;
pSvgFile->GetSvgCalculator()->SetData(pStopElement);
AddObject(pStopElement);
}
END_WHILE
}
bool CGradient::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
{
if (NULL == pRenderer || m_arObjects.empty())

View File

@ -37,13 +37,15 @@ namespace SVG
class CGradient : public CContainer<CStopElement>, public CAppliedObject
{
public:
protected:
CGradient(CSvgReader& oReader);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) override;
void ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile) override;
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;
void ApplyTransform(IRenderer *pRenderer, const TBounds& oBounds, double& dAngle) const;
protected:
@ -58,9 +60,9 @@ namespace SVG
class CLinearGradient : public CGradient
{
public:
friend class CObject;
CLinearGradient(CSvgReader& oReader);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;
@ -73,9 +75,9 @@ namespace SVG
class CRadialGradient : public CGradient
{
public:
friend class CObject;
CRadialGradient(CSvgReader& oReader);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;

View File

@ -5,6 +5,8 @@
#include "../../../BgraFrame.h"
#include "../../../../common/Path.h"
#include "../../../../common/ProcessEnv.h"
#include "../../../../common/Base64.h"
#include "../../../../Common/File.h"
namespace SVG
{

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CImage : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
CImage(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -4,28 +4,44 @@ namespace SVG
{
CLine::CLine(CSvgReader& oReader, CRenderedObject* pParent)
: CPath(oReader, pParent)
{}
{
AddElement(new CMoveElement(Point{0, 0}));
AddElement(new CLineElement(Point{0, 0}));
}
void CLine::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
SvgDigit oX1;
SvgDigit oY1;
SvgDigit oX2;
SvgDigit oY2;
//TODO:: не нравится, подумать как можно сделать иначе
if ("x1" == sName)
oX1.SetValue(oReader.GetText());
{
CMoveElement* pMoveElement{dynamic_cast<CMoveElement*>(operator[](0))};
if (NULL != pMoveElement)
pMoveElement->m_oPoint.dX = oReader.GetDouble();
}
else if ("y1" == sName)
oY1.SetValue(oReader.GetText());
{
CMoveElement* pMoveElement{dynamic_cast<CMoveElement*>(operator[](0))};
if (NULL != pMoveElement)
pMoveElement->m_oPoint.dY = oReader.GetDouble();
}
else if ("x2" == sName)
oX2.SetValue(oReader.GetText());
{
CLineElement* pLineElement{dynamic_cast<CLineElement*>(operator[](1))};
if (NULL != pLineElement)
pLineElement->m_oPoint.dX = oReader.GetDouble();
}
else if ("y2" == sName)
oY2.SetValue(oReader.GetText());
{
CLineElement* pLineElement{dynamic_cast<CLineElement*>(operator[](1))};
if (NULL != pLineElement)
pLineElement->m_oPoint.dY = oReader.GetDouble();
}
else
CRenderedObject::SetAttribute(sName, oReader);
AddElement(new CMoveElement(Point{oX1.ToDouble(NSCSS::Pixel), oY1.ToDouble(NSCSS::Pixel)}));
AddElement(new CLineElement(Point{oX2.ToDouble(NSCSS::Pixel), oY2.ToDouble(NSCSS::Pixel)}));
}
void CLine::SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CLine : public CPath
{
friend class CRenderedObject;
friend class CObject;
CLine(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -7,10 +7,9 @@ namespace SVG
CMarker::CMarker(CSvgReader& oReader)
: CObject(oReader), m_enUnits{EMarkerUnits::StrokeWidth}, m_enOrient{EMarkerOrient::Angle},
m_dAngle(0.), m_oBounds{0., 0., 0., 0.}
{}
CMarker::~CMarker()
{
m_oWindow.m_oWidth.SetValue(3);
m_oWindow.m_oHeight.SetValue(3);
}
ObjectType CMarker::GetType() const
@ -30,7 +29,7 @@ namespace SVG
m_oWindow.m_oHeight.SetValue(oReader.GetDouble());
else if ("viewBox" == sName)
{
std::vector<double> arValues = StrUtils::ReadDoubleValues(oReader.GetText());
const std::vector<double> arValues{StrUtils::ReadDoubleValues(oReader.GetText())};
if (4 == arValues.size())
{
m_oViewBox.m_oX = arValues[0];
@ -55,6 +54,8 @@ namespace SVG
else if (!StrUtils::ReadAngle(wsOrient, m_dAngle))
StrUtils::ReadDoubleValue(wsOrient, m_dAngle);
}
else
CObject::SetAttribute(sName, oReader);
}
void CMarker::SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
@ -65,7 +66,11 @@ namespace SVG
if (NULL == oExternalData.m_pPoints || oExternalData.m_pPoints->empty() || m_arObjects.empty() || (EMarkerUnits::StrokeWidth == m_enUnits && Equals(0., oExternalData.m_dStroke)))
return;
const double dMaxScale = ((EMarkerUnits::StrokeWidth == m_enUnits) ? oExternalData.m_dStroke : 1.) * std::max((m_oWindow.m_oWidth.ToDouble(NSCSS::Pixel) / m_oViewBox.m_oWidth.ToDouble(NSCSS::Pixel)), (m_oWindow.m_oHeight.ToDouble(NSCSS::Pixel) / m_oViewBox.m_oHeight.ToDouble(NSCSS::Pixel)));
const double dMaxScale = ((EMarkerUnits::StrokeWidth == m_enUnits) ? oExternalData.m_dStroke : 1.) *
((!m_oViewBox.m_oWidth.Empty() && !m_oViewBox.m_oHeight.Empty()) ?
std::max((m_oWindow.m_oWidth.ToDouble(NSCSS::Pixel) / m_oViewBox.m_oWidth.ToDouble(NSCSS::Pixel)),
(m_oWindow.m_oHeight.ToDouble(NSCSS::Pixel) / m_oViewBox.m_oHeight.ToDouble(NSCSS::Pixel))) :
1.);
double dM11, dM12, dM21, dM22, dDx, dDy;
pRenderer->GetTransform(&dM11, &dM12, &dM21, &dM22, &dDx, &dDy);

View File

@ -45,9 +45,10 @@ namespace SVG
class CMarker : public CObject, public CContainer<CRenderedObject>
{
public:
friend class CObject;
CMarker(CSvgReader& oReader);
virtual ~CMarker();
public:
virtual ~CMarker() = default;
ObjectType GetType() const override;

View File

@ -14,7 +14,7 @@ namespace SVG
pRenderer->BeginCommand(c_nMaskType);
pRenderer->PathCommandStart();
for (const CRenderedObject* pObject : m_oContainer.m_arObjects)
for (const CRenderedObject* pObject : m_oContainer)
pObject->Draw(pRenderer, pFile, CommandeModeMask);
pRenderer->EndCommand(c_nMaskType);

View File

@ -7,9 +7,9 @@ namespace SVG
{
class CMask : public CClipPath
{
public:
friend class CObject;
CMask(CSvgReader& oReader);
public:
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;
};
}

View File

@ -42,9 +42,6 @@ namespace SVG
: m_oXmlNode(oObject.m_oXmlNode), m_oTransformation(oObject.m_oTransformation)
{}
CObject::~CObject()
{}
void CObject::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("class" == sName)
@ -68,6 +65,11 @@ namespace SVG
SetData(NSCSS::NS_STATIC_FUNCTIONS::GetRules(wsStyles), ushLevel, bHardMode);
}
void CObject::ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile)
{
//TODO:: реализовано в классах там, где нужно
}
void CObject::SetTransform(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"transform"))
@ -201,9 +203,6 @@ namespace SVG
m_pParent(oRenderedObject.m_pParent)
{}
CRenderedObject::~CRenderedObject()
{}
ObjectType CRenderedObject::GetType() const
{
return RendererObject;
@ -223,11 +222,6 @@ namespace SVG
SetMask (mAttributes, ushLevel, bHardMode);
}
void CRenderedObject::ReadChildrens(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator)
{
//TODO:: реализовано в классах там, где нужно
}
std::vector<NSCSS::CNode> CRenderedObject::GetFullPath() const
{
if (NULL == m_pParent)
@ -460,9 +454,6 @@ namespace SVG
: CObject(oReader)
{}
CAppliedObject::~CAppliedObject()
{}
ObjectType CAppliedObject::GetType() const
{
return AppliedObject;

View File

@ -9,7 +9,7 @@
#include "../SvgReader.h"
#include "CStyle.h"
class CSvgFile;
#include "../CSvgFile.h"
namespace SVG
{
@ -44,7 +44,7 @@ namespace SVG
CObject(CSvgReader& oReader);
CObject(const CObject& oObject);
public:
virtual ~CObject();
virtual ~CObject() = default;
virtual ObjectType GetType() const = 0;
@ -54,6 +54,10 @@ namespace SVG
virtual void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) = 0;
template <class T, typename... Args>
static T* Create(CSvgReader& oReader, CSvgFile* pSvgFile, Args&&... args);
virtual void ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile);
void SetTransform(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
void SetClip(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
void SetMask(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
@ -62,35 +66,48 @@ namespace SVG
std::wstring GetId() const;
virtual std::vector<NSCSS::CNode> GetFullPath() const;
private:
protected:
bool ApplyTransform(IRenderer* pRenderer, const SvgTransform* pTransform, Aggplus::CMatrix& oOldMatrix) const;
bool ApplyClip(IRenderer* pRenderer, const TClip* pClip, const CSvgFile *pFile, const TBounds& oBounds) const;
bool ApplyMask(IRenderer* pRenderer, const SvgColor* pMask, const CSvgFile *pFile, const TBounds& oBounds) const;
bool ApplyDef(IRenderer* pRenderer, const CSvgFile *pFile, const std::wstring& wsUrl, const TBounds& oBounds) const;
friend class CRenderedObject;
friend class CAppliedObject;
friend class CUse;
friend class CLine;
friend class CRect;
friend class CPath;
friend class CText;
friend class CTSpan;
friend class CImage;
friend class CCircle;
friend class CPolygon;
friend class CEllipse;
friend class CPolyline;
friend class CGraphicsContainer;
friend class CClipPath;
NSCSS::CNode m_oXmlNode;
TSvgTransformation m_oTransformation;
};
template<class T, typename... Args>
inline T* CObject::Create(CSvgReader& oReader, CSvgFile* pSvgFile, Args&&... args)
{
T* pObject = new T(oReader, std::forward<Args>(args)...);
if (NULL == pObject)
return NULL;
START_READ_ATTRIBUTES(oReader)
pObject->SetAttribute(sAttributeName, oReader);
END_READ_ATTRIBUTES(oReader)
if (NULL == pSvgFile)
return pObject;
if (!pSvgFile->MarkObject(pObject) && AppliedObject == pObject->GetType())
{
delete pObject;
return NULL;
}
const CSvgCalculator* pSvgCalculator{pSvgFile->GetSvgCalculator()};
if (NULL != pSvgCalculator)
pSvgCalculator->SetData(pObject);
pObject->ReadChildrens(oReader, pSvgFile);
return pObject;
}
enum CommandeMode
{
CommandeModeDraw,
@ -107,18 +124,13 @@ namespace SVG
CRenderedObject(CSvgReader& oReader, CRenderedObject* pParent = NULL);
CRenderedObject(const CRenderedObject& oRenderedObject);
public:
virtual ~CRenderedObject();
template <class T, typename... Args>
static T* Create(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator, CRenderedObject* pParent = NULL, Args&&... args);
virtual ~CRenderedObject() = default;
ObjectType GetType() const override;
virtual void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
virtual void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) override;
virtual void ReadChildrens(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator);
virtual bool Draw(IRenderer* pRenderer, const CSvgFile *pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pStyles = NULL, const CRenderedObject* pContextObject = NULL) const = 0;
virtual TBounds GetBounds() const = 0;
@ -159,32 +171,12 @@ namespace SVG
CRenderedObject *m_pParent;
};
template<class T, typename... Args>
inline T* CRenderedObject::Create(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator, CRenderedObject* pParent, Args&&... args)
{
T* pObject = new T(oReader, pParent, std::forward<Args>(args)...);
if (NULL == pObject)
return NULL;
START_READ_ATTRIBUTES(oReader)
pObject->SetAttribute(sAttributeName, oReader);
END_READ_ATTRIBUTES(oReader)
if (NULL != pSvgCalculator)
pSvgCalculator->SetData(pObject);
pObject->ReadChildrens(oReader, pSvgCalculator);
return pObject;
}
class CAppliedObject : public CObject
{
protected:
CAppliedObject(CSvgReader& oReader);
public:
virtual ~CAppliedObject();
virtual ~CAppliedObject() = default;
ObjectType GetType() const override;

View File

@ -8,49 +8,46 @@
namespace SVG
{
IPathElement::~IPathElement()
{
}
#define ISPATHCOMMAND(wchar) L'M' == wchar || L'm' == wchar || L'Z' == wchar || L'z' == wchar || L'L' == wchar || L'l' == wchar || L'H' == wchar || L'h' == wchar || L'V' == wchar || L'v' == wchar || L'C' == wchar || L'c' == wchar || L'S' == wchar || L's' == wchar || L'Q' == wchar || L'q' == wchar || L'T' == wchar || L't' == wchar || L'A' == wchar || L'a' == wchar
// IpathElement
TBounds IPathElement::GetBounds() const
{
TBounds oBounds{DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
for (const Point& oPoint : m_arPoints)
Point IPathElement::GetFirstPoint() const
{
switch (GetType())
{
oBounds.m_dLeft = std::min(oBounds.m_dLeft, oPoint.dX);
oBounds.m_dTop = std::min(oBounds.m_dTop, oPoint.dY);
oBounds.m_dRight = std::max(oBounds.m_dRight, oPoint.dX);
oBounds.m_dBottom = std::max(oBounds.m_dBottom, oPoint.dY);
case Move: return ((CMoveElement*)this)->m_oPoint;
case Line: return ((CLineElement*)this)->m_oPoint;
case CBezier:
case SBezier:
case QBezier:
case TBezier:
case Arc: return ((CCBezierElement*)this)->m_oPoint1;
case Close: return Point{0., 0.};
}
return oBounds;
return Point{0., 0.};
}
UINT IPathElement::GetPointCount() const
Point IPathElement::GetLastPoint() const
{
return m_arPoints.size();
}
switch (GetType())
{
case Move: return ((CMoveElement*)this)->m_oPoint;
case Line: return ((CLineElement*)this)->m_oPoint;
case CBezier:
case SBezier:
case QBezier:
case TBezier:
case Arc: return ((CCBezierElement*)this)->m_oPointE;
case Close: return Point{0., 0.};
}
Point IPathElement::operator[](int nIndex) const
{
if (m_arPoints.empty() || (nIndex > 0 && nIndex >= m_arPoints.size()) || (nIndex < 0 && -nIndex > m_arPoints.size()))
return Point{0., 0.};
return m_arPoints[(nIndex >= 0) ? nIndex : m_arPoints.size() + nIndex];
return Point{0., 0.};
}
//CMoveElement
CMoveElement::CMoveElement(const Point &oPoint)
{
m_arPoints.push_back(oPoint);
}
CMoveElement::~CMoveElement()
{
}
: m_oPoint(oPoint)
{}
EPathElement CMoveElement::GetType() const
{
@ -65,7 +62,7 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (bRelativeCoordinate && NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
CMoveElement *pMoveElement = new CMoveElement(Point{arValues[0], arValues[1]} + oTranslatePoint);
@ -76,19 +73,18 @@ namespace SVG
void CMoveElement::Draw(IRenderer *pRenderer) const
{
if (m_arPoints.empty())
return;
if (NULL != pRenderer)
pRenderer->PathCommandMoveTo(m_oPoint.dX, m_oPoint.dY);
}
pRenderer->PathCommandMoveTo(m_arPoints[0].dX, m_arPoints[0].dY);
TBounds CMoveElement::GetBounds() const
{
return TBounds{m_oPoint.dX, m_oPoint.dY, 1, 1};
}
//CLineElement
CLineElement::CLineElement(const Point &oPoint)
{
m_arPoints.push_back(oPoint);
}
CLineElement::~CLineElement()
: m_oPoint(oPoint)
{}
EPathElement CLineElement::GetType() const
@ -104,7 +100,7 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (bRelativeCoordinate && NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
CLineElement *pLineElement = new CLineElement(Point{arValues[0], arValues[1]} + oTranslatePoint);
@ -121,7 +117,7 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
CLineElement *pLineElement = new CLineElement(Point{oTranslatePoint.dX, arValues[0] + ((bRelativeCoordinate) ? oTranslatePoint.dY : 0)});
@ -138,7 +134,7 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
CLineElement *pLineElement = new CLineElement(Point{arValues[0] + ((bRelativeCoordinate) ? oTranslatePoint.dX : 0), oTranslatePoint.dY});
@ -149,23 +145,19 @@ namespace SVG
void CLineElement::Draw(IRenderer *pRenderer) const
{
if (m_arPoints.empty())
return;
if (NULL != pRenderer)
pRenderer->PathCommandLineTo(m_oPoint.dX, m_oPoint.dY);
}
pRenderer->PathCommandLineTo(m_arPoints[0].dX, m_arPoints[0].dY);
TBounds CLineElement::GetBounds() const
{
return TBounds{m_oPoint.dX, m_oPoint.dY, 1, 1};
}
//CCurveBezierElement
CCBezierElement::CCBezierElement(const Point &oPoint1, const Point &oPoint2, const Point &oPointE, EPathElement enType)
: m_enType(enType)
{
m_arPoints.push_back(oPoint1);
m_arPoints.push_back(oPoint2);
m_arPoints.push_back(oPointE);
}
CCBezierElement::~CCBezierElement()
{
}
: m_oPoint1(oPoint1), m_oPoint2(oPoint2), m_oPointE(oPointE), m_enType(enType)
{}
EPathElement CCBezierElement::GetType() const
{
@ -180,11 +172,11 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (bRelativeCoordinate && NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
CCBezierElement *pCBezierElement = new CCBezierElement(Point{arValues[0], arValues[1]} + oTranslatePoint,
Point{arValues[2], arValues[3]} + oTranslatePoint,
Point{arValues[4], arValues[5]} + oTranslatePoint);
Point{arValues[2], arValues[3]} + oTranslatePoint,
Point{arValues[4], arValues[5]} + oTranslatePoint);
arValues.erase(arValues.begin(), arValues.begin() + 6);
@ -200,14 +192,19 @@ namespace SVG
if (NULL != pPrevElement)
{
oFirstPoint = (*pPrevElement)[-1];
oFirstPoint = pPrevElement->GetLastPoint();
if (bRelativeCoordinate)
oTranslatePoint = oFirstPoint;
}
if (EPathElement::SBezier == pPrevElement->GetType() ||
EPathElement::CBezier == pPrevElement->GetType())
oFirstPoint += oFirstPoint - (*pPrevElement)[-2];
{
CCBezierElement *pBezierElement{dynamic_cast<CCBezierElement*>(pPrevElement)};
if (NULL != pBezierElement)
oFirstPoint += oFirstPoint - pBezierElement->m_oPoint2;
}
CCBezierElement *pCBezierElement = new CCBezierElement(oFirstPoint,
Point{arValues[0], arValues[1]} + oTranslatePoint,
@ -228,7 +225,7 @@ namespace SVG
if (NULL != pPrevElement)
{
oLastPoint = (*pPrevElement)[-1];
oLastPoint = pPrevElement->GetLastPoint();
if (bRelativeCoordinate)
oTranslatePoint = oLastPoint;
}
@ -240,6 +237,14 @@ namespace SVG
return pCBezierElement;
}
bool ItBezierType(EPathElement eType)
{
return EPathElement::CBezier == eType ||
EPathElement::SBezier == eType ||
EPathElement::QBezier == eType ||
EPathElement::TBezier == eType;
}
IPathElement *CCBezierElement::CreateFromTArray(std::vector<double> &arValues, bool bRelativeCoordinate, IPathElement *pPrevElement)
{
if (arValues.size() < 2)
@ -247,10 +252,29 @@ namespace SVG
Point oFirstPoint{0., 0.}, oSecondPoint{0., 0.}, oTranslatePoint{0., 0.};
if (EPathElement::SBezier == pPrevElement->GetType() ||
EPathElement::CBezier == pPrevElement->GetType())
{
CCBezierElement *pBezierElement{dynamic_cast<CCBezierElement*>(pPrevElement)};
if (NULL != pBezierElement)
oFirstPoint += oFirstPoint - pBezierElement->m_oPoint2;
}
if (NULL != pPrevElement)
{
oFirstPoint = (*pPrevElement)[-1];
oSecondPoint = (*pPrevElement)[-2];
oFirstPoint = pPrevElement->GetLastPoint();
if (ItBezierType(pPrevElement->GetType()))
{
CCBezierElement *pBezierElement{dynamic_cast<CCBezierElement*>(pPrevElement)};
if (NULL != pBezierElement)
oSecondPoint = pBezierElement->m_oPoint2;
}
else
oSecondPoint = oFirstPoint;
if (bRelativeCoordinate)
oTranslatePoint = oFirstPoint;
}
@ -282,9 +306,9 @@ namespace SVG
Point oTranslatePoint{0., 0.};
if (bRelativeCoordinate && NULL != pPrevElement)
oTranslatePoint = (*pPrevElement)[-1];
oTranslatePoint = pPrevElement->GetLastPoint();
Point oSrartPoint{(*pPrevElement)[-1]};
Point oSrartPoint{pPrevElement->GetLastPoint()};
Point oSecondPoint{arValues[5] + oTranslatePoint.dX, arValues[6] + oTranslatePoint.dY};
if (oSrartPoint == oSecondPoint)
@ -361,12 +385,26 @@ namespace SVG
void CCBezierElement::Draw(IRenderer *pRenderer) const
{
if (3 != m_arPoints.size())
return;
pRenderer->PathCommandCurveTo(m_oPoint1.dX, m_oPoint1.dY,
m_oPoint2.dX, m_oPoint2.dY,
m_oPointE.dX, m_oPointE.dY);
}
pRenderer->PathCommandCurveTo(m_arPoints[0].dX, m_arPoints[0].dY,
m_arPoints[1].dX, m_arPoints[1].dY,
m_arPoints[2].dX, m_arPoints[2].dY);
#define CHECK_BOUNDS(bounds, point)\
bounds.m_dLeft = std::min(oBounds.m_dLeft, point.dX);\
bounds.m_dTop = std::min(oBounds.m_dTop, point.dY);\
bounds.m_dRight = std::max(oBounds.m_dRight, point.dX);\
bounds.m_dBottom = std::max(oBounds.m_dBottom, point.dY)
TBounds CCBezierElement::GetBounds() const
{
TBounds oBounds{DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
CHECK_BOUNDS(oBounds, m_oPoint1);
CHECK_BOUNDS(oBounds, m_oPoint2);
CHECK_BOUNDS(oBounds, m_oPointE);
return oBounds;
}
inline double ClampSinCos(const double& d)
@ -422,13 +460,6 @@ namespace SVG
}
//CCloseElement
CCloseElement::CCloseElement()
{}
CCloseElement::~CCloseElement()
{
}
EPathElement CCloseElement::GetType() const
{
return EPathElement::Close;
@ -439,6 +470,11 @@ namespace SVG
pRenderer->PathCommandClose();
}
TBounds CCloseElement::GetBounds() const
{
return TBounds{0., 0., 0., 0.};
}
#define LASTELEMENT(array) (array.empty()) ? NULL : array.back()
#define RANGEALIGMENT(value, left, rigth) if (value < left) value = left; else if (value > rigth) value = rigth;
#define EPSILON 0.05
@ -546,17 +582,22 @@ namespace SVG
{
const IPathElement* pFirstElement{m_arElements[unIndex]};
(*oExternalData.m_pPoints)[0].m_oPoint = (*pFirstElement)[0];
(*oExternalData.m_pPoints)[0].m_oPoint = pFirstElement->GetFirstPoint();
if (pStartMarker->NeedExternalAngle())
{
Point oCurent{(*pFirstElement)[0]};
Point oCurent{pFirstElement->GetFirstPoint()};
Point oNext;
if (pFirstElement->GetPointCount() > 1)
oNext = (*pFirstElement)[1];
if (ItBezierType(pFirstElement->GetType()))
{
const CCBezierElement* pBezierElement{dynamic_cast<const CCBezierElement*>(pFirstElement)};
if (NULL != pBezierElement)
oNext = pBezierElement->m_oPoint2;
}
else if (unIndex < m_arElements.size() - 1 && EPathElement::Close != m_arElements[unIndex + 1]->GetType() && EPathElement::Move != m_arElements[unIndex + 1]->GetType())
oNext = (*m_arElements[unIndex + 1])[0];
oNext = m_arElements[unIndex + 1]->GetFirstPoint();
(*oExternalData.m_pPoints)[0].m_dAngle = CALCULATE_ANGLE(oCurent, oNext);
@ -582,12 +623,12 @@ namespace SVG
for (unsigned int unIndex = 1; unIndex < m_arElements.size() - 1; ++unIndex)
{
if (EPathElement::Close != m_arElements[unIndex]->GetType())
(*oExternalData.m_pPoints)[unIndex - 1].m_oPoint = (*m_arElements[unIndex])[-1];
(*oExternalData.m_pPoints)[unIndex - 1].m_oPoint = m_arElements[unIndex]->GetLastPoint();
if (pMidMarker->NeedExternalAngle())
{
const Point oCurrent{(*m_arElements[unIndex])[0]};
const Point oPrev{(*m_arElements[unIndex + 1])[-1]};
const Point oCurrent{m_arElements[unIndex]->GetFirstPoint()};
const Point oPrev{m_arElements[unIndex + 1]->GetLastPoint()};
(*oExternalData.m_pPoints)[unIndex - 1].m_dAngle = CALCULATE_ANGLE(oCurrent, oPrev);
}
@ -613,17 +654,22 @@ namespace SVG
{
const IPathElement* pLastElement{m_arElements[unIndex]};
(*oExternalData.m_pPoints)[0].m_oPoint = (*pLastElement)[-1];
(*oExternalData.m_pPoints)[0].m_oPoint = pLastElement->GetLastPoint();
if (pEndMarker->NeedExternalAngle())
{
Point oCurent{(*pLastElement)[-1]};
Point oCurent{pLastElement->GetLastPoint()};
Point oPrev;
if (pLastElement->GetPointCount() > 1)
oPrev = (*pLastElement)[-2];
else if (unIndex > 0 && EPathElement::Close != m_arElements[unIndex - 1]->GetType() && EPathElement::Move != m_arElements[unIndex - 1]->GetType())
oPrev = (*m_arElements[unIndex - 1])[0];
if (ItBezierType(pLastElement->GetType()))
{
const CCBezierElement* pBezierElement{dynamic_cast<const CCBezierElement*>(pLastElement)};
if (NULL != pBezierElement)
oPrev = pBezierElement->m_oPoint2;
}
else if (unIndex > 0 && EPathElement::Close != m_arElements[unIndex - 1]->GetType())
oPrev = m_arElements[unIndex - 1]->GetFirstPoint();
(*oExternalData.m_pPoints)[0].m_dAngle = CALCULATE_ANGLE(oPrev, oCurent);
}
@ -706,7 +752,7 @@ namespace SVG
if (NULL == pMoveElement)
return;
AddElement(new CCloseElement);
AddElement(new CCloseElement());
oSecondPos = ++oFirstPos;
continue;
}
@ -846,13 +892,13 @@ namespace SVG
case EPathElement::Move:
case EPathElement::Close:
{
m_oPosition = m_oLastPoint = (*m_pCurrentElement)[0];
m_oPosition = m_oLastPoint = m_pCurrentElement->GetFirstPoint();
m_pCurrentElement = (*m_pPath)[m_unIndexElement++];
return Move(dX);
}
case EPathElement::Line:
{
Point oPoint{(*m_pCurrentElement)[0]};
Point oPoint{m_pCurrentElement->GetFirstPoint()};
double dDx = oPoint.dX - m_oPosition.dX;
double dDy = oPoint.dY - m_oPosition.dY;
@ -879,6 +925,11 @@ namespace SVG
case EPathElement::QBezier:
case EPathElement::TBezier:
{
const CCBezierElement* pBezierElement{dynamic_cast<const CCBezierElement*>(m_pCurrentElement)};
if (NULL == pBezierElement)
return false;
Point oCurvePoint{0., 0.};
double dPrevValue = dX;
@ -902,8 +953,8 @@ namespace SVG
RANGEALIGMENT(m_dCurveIndex, 0., 1.);
oCurvePoint.dX = std::pow((1. - m_dCurveIndex), 3) * m_oLastPoint.dX + 3 * std::pow((1. - m_dCurveIndex), 2) * m_dCurveIndex * (*m_pCurrentElement)[0].dX + 3 * (1. - m_dCurveIndex)* std::pow(m_dCurveIndex, 2) * (*m_pCurrentElement)[1].dX + std::pow(m_dCurveIndex, 3) * (*m_pCurrentElement)[2].dX;
oCurvePoint.dY = std::pow((1. - m_dCurveIndex), 3) * m_oLastPoint.dY + 3 * std::pow((1. - m_dCurveIndex), 2) * m_dCurveIndex * (*m_pCurrentElement)[0].dY + 3 * (1. - m_dCurveIndex)* std::pow(m_dCurveIndex, 2) * (*m_pCurrentElement)[1].dY + std::pow(m_dCurveIndex, 3) * (*m_pCurrentElement)[2].dY;
oCurvePoint.dX = std::pow((1. - m_dCurveIndex), 3) * m_oLastPoint.dX + 3 * std::pow((1. - m_dCurveIndex), 2) * m_dCurveIndex * pBezierElement->m_oPoint1.dX + 3 * (1. - m_dCurveIndex)* std::pow(m_dCurveIndex, 2) * pBezierElement->m_oPoint2.dX + std::pow(m_dCurveIndex, 3) * pBezierElement->m_oPointE.dX;
oCurvePoint.dY = std::pow((1. - m_dCurveIndex), 3) * m_oLastPoint.dY + 3 * std::pow((1. - m_dCurveIndex), 2) * m_dCurveIndex * pBezierElement->m_oPoint1.dY + 3 * (1. - m_dCurveIndex)* std::pow(m_dCurveIndex, 2) * pBezierElement->m_oPoint2.dY + std::pow(m_dCurveIndex, 3) * pBezierElement->m_oPointE.dY;
dPrevValue = dX;
@ -912,7 +963,7 @@ namespace SVG
m_dCurveStep = CURVESTEP;
return NextMove(dX, (*m_pCurrentElement)[-1]);
return NextMove(dX, m_pCurrentElement->GetLastPoint());
}
default: return false;
}
@ -927,7 +978,7 @@ namespace SVG
m_unIndexElement = 0;
m_pCurrentElement = (*m_pPath)[m_unIndexElement++];
m_oPosition = m_oLastPoint = (*m_pCurrentElement)[0];
m_oPosition = m_oLastPoint = m_pCurrentElement->GetFirstPoint();
m_dAngle = m_dCurveIndex = 0.;
m_dCurveStep = CURVESTEP;
}

View File

@ -30,57 +30,55 @@ namespace SVG
class IPathElement
{
public:
virtual ~IPathElement();
virtual ~IPathElement() = default;
virtual EPathElement GetType() const = 0;
virtual void Draw(IRenderer* pRenderer) const = 0;
virtual TBounds GetBounds() const = 0;
TBounds GetBounds() const;
UINT GetPointCount() const;
virtual Point operator[](int nIndex) const;
private:
friend class CMoveElement;
friend class CLineElement;
friend class CVLineElement;
friend class CHLineElement;
friend class CCBezierElement;
friend class CSBezierElement;
friend class CQBezierElement;
friend class CTBezierElement;
friend class CArcElement;
friend class CCloseElement;
friend class CMovingPath;
std::vector<Point> m_arPoints;
Point GetFirstPoint() const;
Point GetLastPoint() const;
};
class CMoveElement : public IPathElement
{
public:
CMoveElement(const Point& oPoint);
virtual ~CMoveElement();
virtual ~CMoveElement() = default;
EPathElement GetType() const override;
static CMoveElement* CreateFromArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
void Draw(IRenderer* pRenderer) const override;
TBounds GetBounds() const override;
private:
Point m_oPoint;
friend class IPathElement;
friend class CLine;
};
class CLineElement : public IPathElement
{
public:
CLineElement(const Point& oPoint);
virtual ~CLineElement();
virtual ~CLineElement() = default;
EPathElement GetType() const override;
static CLineElement* CreateFromArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
static CLineElement* CreateFromVArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
static CLineElement* CreateFromHArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
void Draw(IRenderer* pRenderer) const override;
TBounds GetBounds() const override;
Point GetPoint() const;
private:
Point m_oPoint;
friend class IPathElement;
friend class CLine;
};
class CCBezierElement : public IPathElement
{
public:
CCBezierElement(const Point& oPoint1, const Point& oPoint2, const Point& oPointE, EPathElement enType = CBezier);
virtual ~CCBezierElement();
virtual ~CCBezierElement() = default;
EPathElement GetType() const override;
static IPathElement* CreateFromArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
static IPathElement* CreateFromSArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
@ -88,24 +86,33 @@ namespace SVG
static IPathElement* CreateFromTArray(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
static std::vector<IPathElement*> CreateFromArc(std::vector<double>& arValues, bool bRelativeCoordinate, IPathElement* pPrevElement = NULL);
void Draw(IRenderer* pRenderer) const override;
TBounds GetBounds() const override;
private:
static void CalculateArcData(const Point& oFirst, const Point& oSecond, Point& oRadius, Point& oCenter, double dAngle, bool bLargeArc, bool bSweep, double& dStartAngle, double& dSweep);
Point m_oPoint1;
Point m_oPoint2;
Point m_oPointE;
EPathElement m_enType;
friend class IPathElement;
friend class CMovingPath;
friend class CPath;
};
class CCloseElement : public IPathElement
{
public:
CCloseElement();
virtual ~CCloseElement();
CCloseElement() = default;
virtual ~CCloseElement() = default;
EPathElement GetType() const override;
void Draw(IRenderer* pRenderer) const override;
TBounds GetBounds() const override;
};
class CPath : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
protected:
CPath(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
@ -122,7 +129,6 @@ namespace SVG
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile *pFile, int& nTypePath, const CRenderedObject* pContexObject = NULL) const override;
bool DrawMarkers(IRenderer* pRenderer, const CSvgFile *pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const;
TBounds GetBounds() const override;
const int FindIndexFirstNotEmpty(bool bReverseSearch = false) const;

View File

@ -14,8 +14,9 @@ namespace SVG
class CPattern : public CAppliedObject
{
public:
friend class CObject;
CPattern(CSvgReader& oReader, NSFonts::IFontManager *pFontManager = NULL);
public:
virtual ~CPattern();
void SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode) override;

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CPolyline : public CPath
{
friend class CRenderedObject;
friend class CObject;
protected:
CPolyline(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
@ -16,7 +16,7 @@ namespace SVG
class CPolygon : public CPolyline
{
friend class CRenderedObject;
friend class CObject;
CPolygon(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CRect : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
CRect(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
virtual ~CRect();

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CSwitch : public CRenderedObject, public CContainer<CRenderedObject>
{
friend class CRenderedObject;
friend class CObject;
CSwitch(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
bool Draw(IRenderer* pRenderer, const CSvgFile *pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;

View File

@ -7,7 +7,7 @@ namespace SVG
{
class CSymbol : public CGraphicsContainer
{
friend class CRenderedObject;
friend class CObject;
CSymbol(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
bool Draw(IRenderer* pRenderer, const CSvgFile* pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;

View File

@ -27,31 +27,26 @@ namespace SVG
#define MAX_SCALE 100
CTSpan::CTSpan(CSvgReader& oReader, CRenderedObject* pParent, NSFonts::IFontManager* pFontManager, const Point &oPosition)
: CRenderedObject(oReader, pParent), m_pFontManager(pFontManager)
: CRenderedObject(oReader, pParent), m_pFontManager(pFontManager),
m_oX(oPosition.dX), m_oY(oPosition.dY)
{
m_oFont.UpdateSize(DEFAULT_TSPAN_FONT_SIZE, DEFAULT_TSPAN_FONT_SIZE);
m_oX = oPosition.dX;
m_oY = oPosition.dY;
}
CTSpan::CTSpan(const std::wstring &wsText, const Point &oPosition, CRenderedObject *pParent, NSFonts::IFontManager* pFontManager, bool bCheckText)
: CRenderedObject(NSCSS::CNode(L"tspan", L"", L""), pParent), m_pFontManager(pFontManager), m_wsText(wsText)
{
m_oFont.UpdateSize(DEFAULT_TSPAN_FONT_SIZE, DEFAULT_TSPAN_FONT_SIZE);
if (bCheckText)
m_wsText = StrUtils::TrimExtraEnding(m_wsText);
m_oX = oPosition.dX;
m_oY = oPosition.dY;
}
CTSpan::CTSpan(const CTSpan& oTSpan, double dX, const std::wstring& wsText)
: CRenderedObject(oTSpan), m_pFontManager(oTSpan.m_pFontManager),
m_oX(dX), m_oY(oTSpan.m_oY), m_wsText(wsText),
m_oFont(oTSpan.m_oFont), m_oText(oTSpan.m_oText)
{}
{
m_oFont.UpdateSize(DEFAULT_TSPAN_FONT_SIZE, DEFAULT_TSPAN_FONT_SIZE);
}
CTSpan::CTSpan(wchar_t wChar, const Point& oPosition, CRenderedObject* pParent, NSFonts::IFontManager* pFontManager)
: CRenderedObject(NSCSS::CNode(L"tspan", L"", L""), pParent), m_pFontManager(pFontManager),
m_oX(oPosition.dX), m_oY(oPosition.dY)
{
m_oFont.UpdateSize(DEFAULT_TSPAN_FONT_SIZE, DEFAULT_TSPAN_FONT_SIZE);
}
CTSpan::~CTSpan()
{}
@ -117,10 +112,55 @@ namespace SVG
}
}
void CTSpan::ReadChildrens(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator)
void CTSpan::ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile)
{
// SetPositionFromParent(m_pParent);
ReadText(oReader, pSvgCalculator, true);
const int nDepth = oReader.GetDepth();
XmlUtils::XmlNodeType eNodeType = XmlUtils::XmlNodeType_EndElement;
while (oReader.Read(eNodeType) && oReader.GetDepth() >= nDepth && XmlUtils::XmlNodeType_EndElement != eNodeType)
{
if (eNodeType == XmlUtils::XmlNodeType_Text ||
eNodeType == XmlUtils::XmlNodeType_Whitespace ||
eNodeType == XmlUtils::XmlNodeType_SIGNIFICANT_WHITESPACE ||
eNodeType == XmlUtils::XmlNodeType_CDATA)
{
const char* pValue = oReader.GetTextChar();
if('\0' != pValue[0])
{
bool bFoundedSymbol = false;
const char* pCheckValue = pValue;
while ('\0' != *pCheckValue)
{
if (isprint(*pCheckValue++))
{
bFoundedSymbol = true;
break;
}
}
if (!bFoundedSymbol)
continue;
if (m_wsText.empty())
{
NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)pValue, (LONG)strlen(pValue), m_wsText);
continue;
}
std::wstring wsValue;
NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)pValue, (LONG)strlen(pValue), wsValue);
AddObject(new CTSpan(*this, GetBounds().m_dRight, wsValue));
}
}
else if (eNodeType == XmlUtils::XmlNodeType_Element && "tspan" == oReader.GetName())
{
const TBounds oBounds{GetBounds()};
const Point oPoint{oBounds.m_dRight, oBounds.m_dTop};
AddObject(CRenderedObject::Create<CTSpan>(oReader, pSvgFile, this, m_pFontManager, oPoint));
}
}
}
bool CTSpan::Draw(IRenderer *pRenderer, const CSvgFile *pFile, CommandeMode oMode, const TSvgStyles *pOtherStyles, const CRenderedObject* pContexObject) const
@ -338,57 +378,6 @@ namespace SVG
return oBounds;
}
void CTSpan::ReadText(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator, bool bCheckText)
{
const int nDepth = oReader.GetDepth();
XmlUtils::XmlNodeType eNodeType = XmlUtils::XmlNodeType_EndElement;
while (oReader.Read(eNodeType) && oReader.GetDepth() >= nDepth && XmlUtils::XmlNodeType_EndElement != eNodeType)
{
if (eNodeType == XmlUtils::XmlNodeType_Text ||
eNodeType == XmlUtils::XmlNodeType_Whitespace ||
eNodeType == XmlUtils::XmlNodeType_SIGNIFICANT_WHITESPACE ||
eNodeType == XmlUtils::XmlNodeType_CDATA)
{
const char* pValue = oReader.GetTextChar();
if('\0' != pValue[0])
{
bool bFoundedSymbol = false;
const char* pCheckValue = pValue;
while ('\0' != *pCheckValue)
{
if (isprint(*pCheckValue++))
{
bFoundedSymbol = true;
break;
}
}
if (!bFoundedSymbol)
continue;
if (m_wsText.empty())
{
NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)pValue, (LONG)strlen(pValue), m_wsText);
continue;
}
std::wstring wsValue;
NSFile::CUtf8Converter::GetUnicodeStringFromUTF8((BYTE*)pValue, (LONG)strlen(pValue), wsValue);
AddObject(new CTSpan(*this, GetBounds().m_dRight, wsValue));
}
}
else if (eNodeType == XmlUtils::XmlNodeType_Element && "tspan" == oReader.GetName())
{
const TBounds oBounds{GetBounds()};
const Point oPoint{oBounds.m_dRight, oBounds.m_dTop};
AddObject(CRenderedObject::Create<CTSpan>(oReader, pSvgCalculator, this, m_pFontManager, oPoint));
}
}
}
double CTSpan::GetWidth() const
{
if (m_wsText.empty() && m_arObjects.empty())
@ -547,7 +536,7 @@ namespace SVG
for (unsigned int unIndex = 0; unIndex < m_wsText.length(); ++unIndex)
{
arGlyphs.push_back(CTSpan(std::wstring(1, m_wsText[unIndex]), oPosition, m_pParent, m_pFontManager, false));
arGlyphs.push_back(CTSpan(m_wsText[unIndex], oPosition, m_pParent, m_pFontManager));
oPosition.dX += arGlyphs[unIndex].GetWidth();
}

View File

@ -12,18 +12,18 @@ namespace SVG
{
class CTSpan : public CRenderedObject, public CContainer<CTSpan>
{
friend class CRenderedObject;
friend class CObject;
protected:
CTSpan(CSvgReader& oReader, CRenderedObject* pParent = NULL, NSFonts::IFontManager* pFontManager = NULL, const Point& oPosition = {});
CTSpan(const std::wstring& wsText, const Point& oPosition, CRenderedObject* pParent = NULL, NSFonts::IFontManager* pFontManager = NULL, bool bCheckText = true);
CTSpan(const CTSpan& oTSpan, double dX, const std::wstring& wsText);
CTSpan(wchar_t wChar, const Point& oPosition, CRenderedObject* pParent = NULL, NSFonts::IFontManager* pFontManager = NULL);
public:
virtual ~CTSpan();
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;
void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) override;
void ReadChildrens(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator) override;
void ReadChildrens(CSvgReader& oReader, CSvgFile* pSvgFile) override;
bool Draw(IRenderer* pRenderer, const CSvgFile* pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;
@ -38,8 +38,6 @@ namespace SVG
TBounds GetBounds() const override;
void ReadText(CSvgReader& oReader, const CSvgCalculator* pSvgCalculator, bool bCheckText);
double GetWidth() const;
void CorrectFontFamily(std::wstring& wsFontFamily) const;
@ -68,7 +66,7 @@ namespace SVG
class CText : public CTSpan
{
friend class CRenderedObject;
friend class CObject;
protected:
CText(CSvgReader& oReader, CRenderedObject* pParent = NULL, NSFonts::IFontManager* pFontManager = NULL);
public:
@ -77,7 +75,7 @@ namespace SVG
class CTextPath : public CText
{
friend class CRenderedObject;
friend class CObject;
CTextPath(CSvgReader& oReader, CRenderedObject* pParent = NULL, NSFonts::IFontManager* pFontManager = NULL);
public:
void SetAttribute(const std::string& sName, CSvgReader& oReader) override;

View File

@ -8,7 +8,7 @@ namespace SVG
{
class CUse : public CRenderedObject
{
friend class CRenderedObject;
friend class CObject;
CUse(CSvgReader& oReader, CRenderedObject* pParent = NULL);
public:
virtual ~CUse();