Redesigned bounds calculation in svg and refactoring

This commit is contained in:
Kirill Polyakov
2025-10-26 20:53:31 +03:00
parent 7156669830
commit df49a4fbde
27 changed files with 359 additions and 181 deletions

View File

@ -1326,6 +1326,23 @@ namespace NSCSS
return true;
}
CMatrix& CMatrix::operator+=(const CMatrix& oMatrix)
{
m_oValue.insert(m_oValue.end(), oMatrix.m_oValue.begin(), oMatrix.m_oValue.end());
return *this;
}
CMatrix& CMatrix::operator-=(const CMatrix& oMatrix)
{
for (MatrixValues::const_reverse_iterator itElement = oMatrix.m_oValue.crbegin(); itElement < oMatrix.m_oValue.crend(); ++itElement)
{
if (!m_oValue.empty() && m_oValue.back() == *itElement)
m_oValue.pop_back();
}
return *this;
}
// DISPLAY
CDisplay::CDisplay()
{

View File

@ -302,6 +302,8 @@ namespace NSCSS
void ApplyTranform(Aggplus::CMatrix& oMatrix, Aggplus::MatrixOrder order = Aggplus::MatrixOrderPrepend) const;
bool operator==(const CMatrix& oMatrix) const;
CMatrix& operator+=(const CMatrix& oMatrix);
CMatrix& operator-=(const CMatrix& oMatrix);
};
class CEnum : public CValue<int>

View File

@ -45,53 +45,7 @@ bool CSvgFile::OpenFromFile(const std::wstring &wsFile)
bool CSvgFile::GetBounds(double &dX, double &dY, double &dWidth, double &dHeight) const
{
if (NULL == m_pContainer || m_pContainer->Empty())
return false;
SVG::TRect oWindow = m_pContainer->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_pContainer->GetViewBox().m_oWidth.Empty() && !m_pContainer->GetViewBox().m_oWidth.Zero())
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, m_pContainer->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_pContainer->GetViewBox().m_oWidth.ToDouble(NSCSS::Pixel);
if (!oWindow.m_oHeight.Empty() && !oWindow.m_oHeight.Zero())
{
if (NSCSS::Percent == oWindow.m_oHeight.GetUnitMeasure())
{
if (!m_pContainer->GetViewBox().m_oHeight.Empty() && !m_pContainer->GetViewBox().m_oHeight.Zero())
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, m_pContainer->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_pContainer->GetViewBox().m_oHeight.ToDouble(NSCSS::Pixel);
if (DBL_EPSILON > dWidth)
dWidth = SVG_FILE_WIDTH;
if (DBL_EPSILON > dHeight)
dHeight = SVG_FILE_HEIGHT;
return true;
return CalculateFinalSize(true, dX, dY, dWidth, dHeight);
}
const SVG::CSvgCalculator *CSvgFile::GetSvgCalculator() const
@ -170,64 +124,37 @@ bool CSvgFile::Draw(IRenderer *pRenderer, double dX, double dY, double dWidth, d
if (NULL == pRenderer || NULL == m_pContainer || m_pContainer->Empty())
return false;
SVG::TRect oWindow = m_pContainer->GetWindow();
SVG::TRect oViewBox = m_pContainer->GetViewBox();
double dFileX, dFileY, dFileWidth, dFileHeight;
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))
if (!CalculateFinalSize(false, dFileX, dFileY, dFileWidth, dFileHeight))
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;
const double dM11 = dWidth / dFileWidth;
const double dM22 = dHeight / dFileHeight;
double dScaleX = 1, dScaleY = 1;
double dScaleX = 1.,
dScaleY = 1.;
double dTranslateX = dFileX * dM11,
dTranslateY = dFileY * dM22;
if (!SVG::Equals(0., dViewBoxWidth))
dScaleX = dWindowWidth / dViewBoxWidth;
const SVG::TRect oViewBox{m_pContainer->GetViewBox()};
if (!SVG::Equals(0., dViewBoxHeight))
dScaleY = dWindowHeight / dViewBoxHeight;
if (!oViewBox.m_oWidth.Empty() && !oViewBox.m_oHeight.Empty())
{
dScaleX = dFileWidth / oViewBox.m_oWidth .ToDouble(NSCSS::Pixel, SVG_FILE_WIDTH );
dScaleY = dFileHeight / oViewBox.m_oHeight.ToDouble(NSCSS::Pixel, SVG_FILE_HEIGHT);
double dMinScale = std::min(dScaleX, dScaleY);
dTranslateX -= oViewBox.m_oX.ToDouble(NSCSS::Pixel) * dScaleX * dM11;
dTranslateY -= oViewBox.m_oY.ToDouble(NSCSS::Pixel) * dScaleY * dM22;
}
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);
const double dMinScale = std::min(dScaleX, dScaleY);
pRenderer->SetTransform(dM11 * dMinScale, 0, 0, dM22 * dMinScale, dTranslateX, dTranslateY);
bool bResult = m_pContainer->Draw(pRenderer, this);
@ -247,3 +174,141 @@ void CSvgFile::Clear()
m_mMarkedObjects.clear();
m_wsWorkingDirectory.clear();
}
bool CSvgFile::CalculateFinalSize(bool bUseViewBox, double& dX, double& dY, double& dWidth, double& dHeight) const
{
if (NULL == m_pContainer || m_pContainer->Empty())
return false;
const SVG::TRect oWindow = m_pContainer->GetWindow();
const SVG::TRect oViewBox = m_pContainer->GetViewBox();
const double dViewBoxWidth {oViewBox.m_oWidth .ToDouble()};
const double dViewBoxHeigth{oViewBox.m_oHeight.ToDouble()};
dX = 0.;
dY = 0.;
dWidth = 0.;
dHeight = 0.;
#define GET_PREV_WIDTH_VALUE ((NSCSS::UnitMeasure::Em == oWindow.m_oWidth.GetUnitMeasure() || NSCSS::UnitMeasure::Rem == oWindow.m_oWidth.GetUnitMeasure()) ? DEFAULT_FONT_SIZE : ((!SVG::Equals(0., dViewBoxWidth )) ? dViewBoxWidth : SVG_FILE_WIDTH))
#define GET_PREV_HEIGHT_VALUE ((NSCSS::UnitMeasure::Em == oWindow.m_oHeight.GetUnitMeasure() || NSCSS::UnitMeasure::Rem == oWindow.m_oHeight.GetUnitMeasure()) ? DEFAULT_FONT_SIZE : ((!SVG::Equals(0., dViewBoxHeigth )) ? dViewBoxHeigth : SVG_FILE_HEIGHT))
if (!oWindow.m_oWidth.Empty() && !oWindow.m_oHeight.Empty())
{
dWidth = oWindow.m_oWidth .ToDouble(NSCSS::Pixel, GET_PREV_WIDTH_VALUE);
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, GET_PREV_HEIGHT_VALUE);
return true;
}
if (bUseViewBox)
{
if (!oViewBox.m_oWidth.Empty() && !oViewBox.m_oHeight.Empty())
{
if (!oWindow.m_oWidth.Empty())
{
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, GET_PREV_WIDTH_VALUE);
const double dAspectRatio{dViewBoxWidth / dViewBoxHeigth};
dHeight = dWidth / dAspectRatio;
return true;
}
if (!oWindow.m_oHeight.Empty())
{
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, GET_PREV_HEIGHT_VALUE);
const double dAspectRatio{dViewBoxWidth / dViewBoxHeigth};
dWidth = dHeight * dAspectRatio;
return true;
}
dX = oViewBox.m_oX.ToDouble();
dY = oViewBox.m_oY.ToDouble();
dWidth = dViewBoxWidth;
dHeight = dViewBoxHeigth;
return true;
}
}
if (!oWindow.m_oWidth.Empty() || !oWindow.m_oHeight.Empty())
{
if (!oViewBox.m_oWidth.Empty() && !oViewBox.m_oHeight.Empty())
{
const double dAspectRatio{dViewBoxWidth / dViewBoxHeigth};
if (!oWindow.m_oWidth.Empty())
{
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, GET_PREV_WIDTH_VALUE);
dHeight = dWidth / dAspectRatio;
}
else if (!oWindow.m_oHeight.Empty())
{
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, GET_PREV_HEIGHT_VALUE);
dWidth = dHeight * dAspectRatio;
}
return true;
}
if (NULL != m_pContainer && !m_pContainer->Empty())
{
SVG::SvgMatrix oTransform;
const SVG::TBounds oBounds{m_pContainer->GetBounds(&oTransform)};
const double dContentWidth {oBounds.m_dRight - oBounds.m_dLeft};
const double dContentHeight{oBounds.m_dBottom - oBounds.m_dTop };
const double dAspectRatio{dContentWidth / dContentHeight};
if (!oWindow.m_oWidth.Empty())
{
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, GET_PREV_WIDTH_VALUE);
dHeight = dWidth / dAspectRatio;
}
else if (!oWindow.m_oHeight.Empty())
{
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, GET_PREV_HEIGHT_VALUE);
dWidth = dHeight * dAspectRatio;
}
dX = oBounds.m_dLeft;
dY = oBounds.m_dTop;
return true;
}
if (!oWindow.m_oWidth.Empty())
{
dWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, GET_PREV_WIDTH_VALUE);
dHeight = SVG_FILE_HEIGHT;
}
else if (!oWindow.m_oHeight.Empty())
{
dHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, GET_PREV_HEIGHT_VALUE);
dWidth = SVG_FILE_WIDTH;
}
return true;
}
if (NULL != m_pContainer && !m_pContainer->Empty())
{
SVG::SvgMatrix oTransform;
const SVG::TBounds oBounds{m_pContainer->GetBounds(&oTransform)};
dX = oBounds.m_dLeft;
dY = oBounds.m_dTop;
dWidth = oBounds.m_dRight - oBounds.m_dLeft;
dHeight = oBounds.m_dBottom - oBounds.m_dTop;
return true;
}
dWidth = SVG_FILE_WIDTH;
dHeight = SVG_FILE_HEIGHT;
return true;
}

View File

@ -43,6 +43,8 @@ class CSvgFile
private:
void Clear();
bool CalculateFinalSize(bool bUseViewBox, double& dX, double& dY, double& dWidth, double& dHeight) const;
SVG::CGraphicsContainer *m_pContainer;
SVG::CSvgCalculator m_oSvgCalculator;
NSFonts::IFontManager *m_pFontManager;

View File

@ -15,11 +15,11 @@ namespace SVG
void CCircle::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("cx" == sName)
m_oCx.SetValue(oReader.GetDouble());
m_oCx.SetValue(oReader.GetText());
else if ("cy" == sName)
m_oCy.SetValue(oReader.GetDouble());
m_oCy.SetValue(oReader.GetText());
else if ("r" == sName)
m_oR.SetValue(oReader.GetDouble());
m_oR.SetValue(oReader.GetText());
else
CRenderedObject::SetAttribute(sName, oReader);
}
@ -62,7 +62,7 @@ namespace SVG
nTypePath += c_nWindingFillMode;
}
TBounds CCircle::GetBounds() const
TBounds CCircle::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds;
@ -71,6 +71,16 @@ namespace SVG
oBounds.m_dRight = (m_oCx + m_oR).ToDouble(NSCSS::Pixel);
oBounds.m_dBottom = (m_oCy + m_oR).ToDouble(NSCSS::Pixel);
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
}
return oBounds;
}

View File

@ -18,7 +18,7 @@ namespace SVG
private:
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile *pFile, int& nTypePath, const CRenderedObject* pContexObject = NULL) const override;
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
SvgDigit m_oCx;
SvgDigit m_oCy;

View File

@ -12,13 +12,13 @@ namespace SVG
void CGraphicsContainer::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x" == sName)
m_oWindow.m_oX.SetValue(oReader.GetDouble());
m_oWindow.m_oX.SetValue(oReader.GetText());
else if ("y" == sName)
m_oWindow.m_oY.SetValue(oReader.GetDouble());
m_oWindow.m_oY.SetValue(oReader.GetText());
else if ("width" == sName)
m_oWindow.m_oWidth.SetValue(oReader.GetDouble());
m_oWindow.m_oWidth.SetValue(oReader.GetText());
else if ("height" == sName)
m_oWindow.m_oHeight.SetValue(oReader.GetDouble());
m_oWindow.m_oHeight.SetValue(oReader.GetText());
else if ("viewBox" == sName)
{
const std::vector<double> arValues{StrUtils::ReadDoubleValues(oReader.GetText())};
@ -56,13 +56,10 @@ namespace SVG
TRect CGraphicsContainer::GetViewBox() const
{
if (m_oViewBox.m_oWidth.Empty() || m_oViewBox.m_oHeight.Empty())
return m_oWindow;
return m_oViewBox;
}
TBounds CGraphicsContainer::GetBounds() const
TBounds CGraphicsContainer::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds, oTempBounds;
@ -71,15 +68,21 @@ namespace SVG
oBounds.m_dRight += m_oWindow.m_oWidth.ToDouble(NSCSS::Pixel);
oBounds.m_dBottom += m_oWindow.m_oHeight.ToDouble(NSCSS::Pixel);
if (nullptr != pTransform)
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
for (const CRenderedObject* pObject : m_arObjects)
{
oTempBounds = pObject->GetBounds();
oTempBounds = pObject->GetBounds(pTransform);
oBounds.m_dLeft = std::min(oBounds.m_dLeft, oTempBounds.m_dLeft);
oBounds.m_dTop = std::min(oBounds.m_dTop, oTempBounds.m_dTop);
oBounds.m_dRight = std::max(oBounds.m_dRight, oTempBounds.m_dRight);
oBounds.m_dBottom = std::max(oBounds.m_dBottom, oTempBounds.m_dBottom);
}
if (nullptr != pTransform)
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
return oBounds;
}

View File

@ -89,8 +89,8 @@ namespace SVG
TRect GetWindow() const;
TRect GetViewBox() const;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
private:
TBounds GetBounds() const override;
friend class CPattern;
friend class CMarker;

View File

@ -19,13 +19,13 @@ namespace SVG
void CEllipse::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("cx" == sName)
m_oCx.SetValue(oReader.GetDouble());
m_oCx.SetValue(oReader.GetText());
else if ("cy" == sName)
m_oCy.SetValue(oReader.GetDouble());
m_oCy.SetValue(oReader.GetText());
else if ("rx" == sName)
m_oRx.SetValue(oReader.GetDouble());
m_oRx.SetValue(oReader.GetText());
else if ("ry" == sName)
m_oRy.SetValue(oReader.GetDouble());
m_oRy.SetValue(oReader.GetText());
else
CRenderedObject::SetAttribute(sName, oReader);
}
@ -64,7 +64,7 @@ namespace SVG
nTypePath += c_nWindingFillMode;
}
TBounds CEllipse::GetBounds() const
TBounds CEllipse::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds;
@ -73,6 +73,16 @@ namespace SVG
oBounds.m_dRight = oBounds.m_dLeft + m_oRx.ToDouble(NSCSS::Pixel);
oBounds.m_dBottom = oBounds.m_dTop + m_oRy.ToDouble(NSCSS::Pixel);;
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
}
return oBounds;
}
}

View File

@ -18,7 +18,7 @@ namespace SVG
private:
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile *pFile, int& nTypePath, const CRenderedObject* pContexObject = NULL) const override;
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
SvgDigit m_oCx;
SvgDigit m_oCy;

View File

@ -51,7 +51,7 @@ namespace SVG
else if ("font-weight" == sName)
m_oArguments.m_wsFontWidght = oReader.GetText();
else if ("horiz-adv-x" == sName)
m_oHorizAdvX.SetValue(oReader.GetDouble());
m_oHorizAdvX.SetValue(oReader.GetText());
else
CAppliedObject::SetAttribute(sName, oReader);
}

View File

@ -149,13 +149,13 @@ namespace SVG
void CLinearGradient::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x1" == sName)
m_oX1.SetValue(oReader.GetDouble());
m_oX1.SetValue(oReader.GetText());
else if ("y1" == sName)
m_oY1.SetValue(oReader.GetDouble());
m_oY1.SetValue(oReader.GetText());
else if ("x2" == sName)
m_oX2.SetValue(oReader.GetDouble());
m_oX2.SetValue(oReader.GetText());
else if ("y2" == sName)
m_oY2.SetValue(oReader.GetDouble());
m_oY2.SetValue(oReader.GetText());
else
CGradient::SetAttribute(sName, oReader);
}
@ -210,11 +210,11 @@ namespace SVG
void CRadialGradient::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("cx" == sName)
m_oCx.SetValue(oReader.GetDouble());
m_oCx.SetValue(oReader.GetText());
else if ("cy" == sName)
m_oCy.SetValue(oReader.GetDouble());
m_oCy.SetValue(oReader.GetText());
else if ("r" == sName)
m_oR.SetValue(oReader.GetDouble());
m_oR.SetValue(oReader.GetText());
else
CGradient::SetAttribute(sName, oReader);
}

View File

@ -17,13 +17,13 @@ namespace SVG
void CImage::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x" == sName)
m_oRect.m_oX.SetValue(oReader.GetDouble());
m_oRect.m_oX.SetValue(oReader.GetText());
else if ("y" == sName)
m_oRect.m_oY.SetValue(oReader.GetDouble());
m_oRect.m_oY.SetValue(oReader.GetText());
else if ("width" == sName)
m_oRect.m_oWidth.SetValue(oReader.GetDouble());
m_oRect.m_oWidth.SetValue(oReader.GetText());
else if ("height" == sName)
m_oRect.m_oHeight.SetValue(oReader.GetDouble());
m_oRect.m_oHeight.SetValue(oReader.GetText());
else if ("href" == sName || "xlink:href" == sName)
m_wsHref = oReader.GetText(); // TODO:: В дальнейшем возможно стоит реализовать отдельный класс CHref для всех типов ссылок
else
@ -135,7 +135,7 @@ namespace SVG
return true;
}
TBounds CImage::GetBounds() const
TBounds CImage::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds;
@ -144,6 +144,16 @@ namespace SVG
oBounds.m_dRight = oBounds.m_dLeft + m_oRect.m_oWidth.ToDouble(NSCSS::Pixel);
oBounds.m_dBottom = oBounds.m_dTop + m_oRect.m_oHeight.ToDouble(NSCSS::Pixel);
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
}
return oBounds;
}
}

View File

@ -14,7 +14,7 @@ namespace SVG
bool Draw(IRenderer* pRenderer, const CSvgFile *pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;
private:
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
TRect m_oRect;
std::wstring m_wsHref;

View File

@ -20,13 +20,13 @@ namespace SVG
void CMarker::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("refX" == sName)
m_oWindow.m_oX.SetValue(oReader.GetDouble());
m_oWindow.m_oX.SetValue(oReader.GetText());
else if ("refY" == sName)
m_oWindow.m_oY.SetValue(oReader.GetDouble());
m_oWindow.m_oY.SetValue(oReader.GetText());
else if ("markerWidth" == sName)
m_oWindow.m_oWidth.SetValue(oReader.GetDouble());
m_oWindow.m_oWidth.SetValue(oReader.GetText());
else if ("markerHeight" == sName)
m_oWindow.m_oHeight.SetValue(oReader.GetDouble());
m_oWindow.m_oHeight.SetValue(oReader.GetText());
else if ("viewBox" == sName)
{
const std::vector<double> arValues{StrUtils::ReadDoubleValues(oReader.GetText())};

View File

@ -133,7 +133,7 @@ namespace SVG
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;
virtual TBounds GetBounds(SvgMatrix* pTransform = nullptr) const = 0;
std::vector<NSCSS::CNode> GetFullPath() const override;
private:

View File

@ -703,7 +703,7 @@ namespace SVG
}
}
TBounds CPath::GetBounds() const
TBounds CPath::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds{DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX}, oTempBounds;
@ -717,6 +717,16 @@ namespace SVG
oBounds.m_dBottom = std::max(oBounds.m_dBottom, oTempBounds.m_dBottom);
}
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
}
return oBounds;
}

View File

@ -129,7 +129,7 @@ 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;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
const int FindIndexFirstNotEmpty(bool bReverseSearch = false) const;

View File

@ -14,17 +14,17 @@ namespace SVG
void CRect::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x" == sName)
m_oRect.m_oX.SetValue(oReader.GetDouble());
m_oRect.m_oX.SetValue(oReader.GetText());
else if ("y" == sName)
m_oRect.m_oY.SetValue(oReader.GetDouble());
m_oRect.m_oY.SetValue(oReader.GetText());
else if ("width" == sName)
m_oRect.m_oWidth.SetValue(oReader.GetDouble());
m_oRect.m_oWidth.SetValue(oReader.GetText());
else if ("height" == sName)
m_oRect.m_oHeight.SetValue(oReader.GetDouble());
m_oRect.m_oHeight.SetValue(oReader.GetText());
else if ("rx" == sName)
m_oRx.SetValue(oReader.GetDouble());
m_oRx.SetValue(oReader.GetText());
else if ("ry" == sName)
m_oRy.SetValue(oReader.GetDouble());
m_oRy.SetValue(oReader.GetText());
else
CRenderedObject::SetAttribute(sName, oReader);
@ -103,7 +103,7 @@ namespace SVG
nTypePath += c_nWindingFillMode;
}
TBounds CRect::GetBounds() const
TBounds CRect::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds;
@ -112,6 +112,16 @@ namespace SVG
oBounds.m_dRight = oBounds.m_dLeft + m_oRect.m_oWidth.ToDouble(NSCSS::Pixel);
oBounds.m_dBottom = oBounds.m_dTop + m_oRect.m_oHeight.ToDouble(NSCSS::Pixel);
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
}
return oBounds;
}
}

View File

@ -21,7 +21,7 @@ namespace SVG
private:
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile* pFile, int& nTypePath, const CRenderedObject* pContexObject = NULL) const override;
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
TRect m_oRect;

View File

@ -17,7 +17,7 @@ namespace SVG
return false;
}
TBounds CSwitch::GetBounds() const
TBounds CSwitch::GetBounds(SvgMatrix* pTransform) const
{
for (const CRenderedObject* pObject : m_arObjects)
if (NULL != pObject)

View File

@ -12,7 +12,7 @@ namespace SVG
public:
bool Draw(IRenderer* pRenderer, const CSvgFile *pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
};
}
#endif // CSWITCH_H

View File

@ -19,7 +19,6 @@
namespace SVG
{
#define DEFAULT_TSPAN_FONT_SIZE 16
#define DefaultFontFamily L"Times New Roman"
#define MIN_FONT_SIZE 5
#define MAX_FONT_SIZE 100
@ -29,24 +28,18 @@ namespace SVG
CTSpan::CTSpan(CSvgReader& oReader, CRenderedObject* pParent, NSFonts::IFontManager* pFontManager, const Point &oPosition)
: 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);
}
{}
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()
{}
@ -54,9 +47,9 @@ namespace SVG
void CTSpan::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x" == sName)
m_oX.SetValue(oReader.GetDouble());
m_oX.SetValue(oReader.GetText());
else if ("y" == sName)
m_oY.SetValue(oReader.GetDouble());
m_oY.SetValue(oReader.GetText());
else
CRenderedObject::SetAttribute(sName, oReader);
}
@ -70,13 +63,22 @@ namespace SVG
//FONT
if (mAttributes.end() != mAttributes.find(L"font"))
{
m_oFont.SetValue(mAttributes.at(L"font"), ushLevel, bHardMode);
UpdateFontSize();
}
if (mAttributes.end() != mAttributes.find(L"font-size"))
{
m_oFont.SetSize(mAttributes.at(L"font-size"), ushLevel, bHardMode);
UpdateFontSize();
}
if (mAttributes.end() != mAttributes.find(L"font-size-adjust"))
{
m_oFont.SetSize(mAttributes.at(L"font-size-adjust"), ushLevel, bHardMode);
UpdateFontSize();
}
if (mAttributes.end() != mAttributes.find(L"font-stretch"))
m_oFont.SetStretch(mAttributes.at(L"font-stretch"), ushLevel, bHardMode);
@ -94,7 +96,10 @@ namespace SVG
m_oFont.SetFamily(mAttributes.at(L"font-family"), ushLevel, bHardMode);
if (mAttributes.end() != mAttributes.find(L"line-height"))
{
m_oFont.SetLineHeight(mAttributes.at(L"line-height"), ushLevel, bHardMode);
UpdateFontSize();
}
//TEXT
if (mAttributes.end() != mAttributes.find(L"text-anchor"))
@ -131,7 +136,7 @@ namespace SVG
const char* pCheckValue = pValue;
while ('\0' != *pCheckValue)
{
if (isprint(*pCheckValue++))
if (0x32 >= *pCheckValue++)
{
bFoundedSymbol = true;
break;
@ -226,7 +231,7 @@ namespace SVG
void CTSpan::ApplyFont(IRenderer* pRenderer, double& dX, double& dY) const
{
std::wstring wsFontFamily = DefaultFontFamily;
double dFontSize = m_oFont.GetSize().ToDouble(NSCSS::Pixel) * 72. / 25.4;
double dFontSize = ((!m_oFont.GetSize().Empty()) ? m_oFont.GetSize().ToDouble(NSCSS::Pixel) : DEFAULT_FONT_SIZE) * 72. / 25.4;
Normalize(pRenderer, dX, dY, dFontSize);
@ -260,7 +265,6 @@ namespace SVG
double dKoef = 25.4 / 72.;
NSFonts::IFontFile* pFontFile = m_pFontManager->GetFile();
if (pFontFile)
@ -326,6 +330,22 @@ namespace SVG
pRenderer->put_BrushAlpha1(255);
}
void CTSpan::UpdateFontSize()
{
if (NULL != m_pParent)
{
const CTSpan* pParentTSpan{dynamic_cast<const CTSpan*>(m_pParent)};
if (NULL != pParentTSpan)
{
m_oFont.UpdateSize((!pParentTSpan->m_oFont.GetSize().Empty()) ? pParentTSpan->m_oFont.GetSize().ToDouble(NSCSS::Pixel) : DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
return;
}
}
m_oFont.UpdateSize(DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
}
bool CTSpan::UseExternalFont(const CSvgFile *pFile, double dX, double dY, IRenderer *pRenderer, CommandeMode oMode, const TSvgStyles *pOtherStyles, const CRenderedObject* pContexObject) const
{
std::wstring wsFontFamily = DefaultFontFamily;
@ -353,21 +373,30 @@ namespace SVG
return true;
}
TBounds CTSpan::GetBounds() const
TBounds CTSpan::GetBounds(SvgMatrix* pTransform) const
{
TBounds oBounds;
oBounds.m_dLeft = m_oX.ToDouble(NSCSS::Pixel);
oBounds.m_dTop = m_oY.ToDouble(NSCSS::Pixel);
oBounds.m_dRight = oBounds.m_dLeft + GetWidth();
oBounds.m_dBottom = oBounds.m_dTop + m_oFont.GetSize().ToDouble(NSCSS::Pixel) * 72. / 25.4;
oBounds.m_dBottom = m_oY.ToDouble(NSCSS::Pixel);
oBounds.m_dTop = oBounds.m_dBottom + ((!m_oFont.GetSize().Empty()) ? m_oFont.GetSize().ToDouble(NSCSS::Pixel) : DEFAULT_FONT_SIZE);
if (nullptr != pTransform)
{
*pTransform += m_oTransformation.m_oTransform.GetMatrix();
pTransform->GetFinalValue().TransformPoint(oBounds.m_dLeft, oBounds.m_dTop );
pTransform->GetFinalValue().TransformPoint(oBounds.m_dRight, oBounds.m_dBottom);
}
if (!m_arObjects.empty())
{
TBounds oTempBounds;
for (const CRenderedObject* pObject : m_arObjects)
{
oTempBounds = pObject->GetBounds();
oTempBounds = pObject->GetBounds(pTransform);
oBounds.m_dLeft = std::min(oBounds.m_dLeft, oTempBounds.m_dLeft);
oBounds.m_dTop = std::min(oBounds.m_dTop, oTempBounds.m_dTop);
oBounds.m_dRight = std::max(oBounds.m_dRight, oTempBounds.m_dRight);
@ -375,6 +404,9 @@ namespace SVG
}
}
if (nullptr != pTransform)
*pTransform -= m_oTransformation.m_oTransform.GetMatrix();
return oBounds;
}
@ -384,7 +416,7 @@ namespace SVG
return 0.;
std::wstring wsName = DefaultFontFamily;
double dSize = (!m_oFont.GetSize().Zero()) ? m_oFont.GetSize().ToDouble(NSCSS::Pixel) : DEFAULT_TSPAN_FONT_SIZE;
const double dSize = (!m_oFont.GetSize().Empty()) ? m_oFont.GetSize().ToDouble(NSCSS::Pixel) : DEFAULT_FONT_SIZE;
if (!m_oFont.GetFamily().Empty())
{
@ -545,7 +577,9 @@ namespace SVG
CText::CText(CSvgReader& oReader, CRenderedObject *pParent, NSFonts::IFontManager* pFontManager)
: CTSpan(oReader, pParent, pFontManager)
{}
{
m_oFont.UpdateSize(DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE);
}
bool CText::Draw(IRenderer *pRenderer, const CSvgFile *pFile, CommandeMode oMode, const TSvgStyles *pOtherStyles, const CRenderedObject* pContexObject) const
{

View File

@ -34,9 +34,10 @@ namespace SVG
void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile* pFile, int& nTypePath, const CRenderedObject* pContexObject = NULL) const override;
void ApplyFont(IRenderer* pRenderer, double& dX, double& dY) const;
void UpdateFontSize();
bool UseExternalFont(const CSvgFile* pFile, double dX, double dY, IRenderer* pRenderer, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const;
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
double GetWidth() const;
void CorrectFontFamily(std::wstring& wsFontFamily) const;

View File

@ -13,13 +13,13 @@ namespace SVG
void CUse::SetAttribute(const std::string& sName, CSvgReader& oReader)
{
if ("x" == sName)
m_oX.SetValue(oReader.GetDouble());
m_oX.SetValue(oReader.GetText());
else if ("y" == sName)
m_oY.SetValue(oReader.GetDouble());
m_oY.SetValue(oReader.GetText());
else if ("width" == sName)
m_oWidth.SetValue(oReader.GetDouble());
m_oWidth.SetValue(oReader.GetText());
else if ("height" == sName)
m_oHeight.SetValue(oReader.GetDouble());
m_oHeight.SetValue(oReader.GetText());
else if ("href" == sName || "xlink:href" == sName)
m_wsHref = oReader.GetText();
else
@ -73,7 +73,7 @@ namespace SVG
return bResult;
}
TBounds CUse::GetBounds() const
TBounds CUse::GetBounds(SvgMatrix* pTransform) const
{
return TBounds{0., 0., 0., 0.};
}

View File

@ -19,7 +19,7 @@ namespace SVG
bool Draw(IRenderer* pRenderer, const CSvgFile* pFile, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL, const CRenderedObject* pContexObject = NULL) const override;
private:
TBounds GetBounds() const override;
TBounds GetBounds(SvgMatrix* pTransform = nullptr) const override;
CRenderedObject *m_pUsedObject;

View File

@ -9,17 +9,21 @@
namespace SVG
{
#define MapCI std::map<std::wstring, std::wstring>::const_iterator
using MapCI = std::map<std::wstring, std::wstring>::const_iterator;
#define SvgDigit NSCSS::NSProperties::CDigit
#define SvgString NSCSS::NSProperties::CString
#define SvgColor NSCSS::NSProperties::CColor
#define SvgURL NSCSS::NSProperties::CURL
#define SvgEnum NSCSS::NSProperties::CEnum
using SvgDigit = NSCSS::NSProperties::CDigit;
using SvgString = NSCSS::NSProperties::CString;
using SvgColor = NSCSS::NSProperties::CColor;
using SvgURL = NSCSS::NSProperties::CURL;
using SvgEnum = NSCSS::NSProperties::CEnum;
#define SvgTransform NSCSS::NSProperties::CTransform
#define SvgFont NSCSS::NSProperties::CFont
#define SvgText NSCSS::NSProperties::CText
using SvgTransform = NSCSS::NSProperties::CTransform;
using SvgFont = NSCSS::NSProperties::CFont;
using SvgText = NSCSS::NSProperties::CText;
using SvgMatrix = NSCSS::NSProperties::CMatrix;
#define DEFAULT_FONT_SIZE 16
struct TStroke
{