Merge pull request #1279 from ONLYOFFICE/fix/SvgConversion

Fixes in svg conversion
This commit is contained in:
Oleg Korshul
2023-09-18 20:36:43 +03:00
committed by GitHub
21 changed files with 355 additions and 221 deletions

View File

@ -9,7 +9,7 @@ namespace NSCSS
{
namespace NSProperties
{
#define CHECK_CONDITIONS (m_bImportant || unLevel <= m_unLevel)
#define CHECK_CONDITIONS (m_bImportant || unLevel < m_unLevel)
static bool CutImportant(std::wstring& wsValue)
{
@ -435,7 +435,7 @@ namespace NSCSS
bool CColor::SetValue(const std::wstring &wsValue, unsigned int unLevel, bool bHardMode)
{
if (wsValue.empty() || (CHECK_CONDITIONS && !bHardMode))
if ((CHECK_CONDITIONS && !bHardMode) || (wsValue.empty() && unLevel == m_unLevel))
return false;
if (wsValue.empty())
@ -665,6 +665,10 @@ namespace NSCSS
enType = TransformScale;
else if (std::wstring::npos != wsTransform.find(L"rotate"))
enType = TransformRotate;
else if (std::wstring::npos != wsTransform.find(L"skewx"))
enType = TransformSkewX;
else if (std::wstring::npos != wsTransform.find(L"skewy"))
enType = TransformSkewY;
else
{
Clear();
@ -739,6 +743,16 @@ namespace NSCSS
else
return false;
break;
}
case TransformSkewX:
case TransformSkewY:
{
if (arValues.empty())
return false;
m_oValue.push_back(std::make_pair(std::vector<double>{arValues[0]}, enType));
break;
}
}
@ -855,6 +869,16 @@ namespace NSCSS
oMatrix.RotateAt(oElement.first[0], -oElement.first[1], -oElement.first[2]);
break;
}
case TransformSkewX:
{
oMatrix.Shear(oElement.first[0] * 3.14 / 180.0, 0);
break;
}
case TransformSkewY:
{
oMatrix.Shear(0, oElement.first[0] * 3.14 / 180.0);
break;
}
default: break;
}
}
@ -890,6 +914,16 @@ namespace NSCSS
oMatrix.RotateAt(oElement.first[0], -oElement.first[1], -oElement.first[2], order);
break;
}
case TransformSkewX:
{
oMatrix.Shear(oElement.first[0] * 3.14 / 180.0, 0, order);
break;
}
case TransformSkewY:
{
oMatrix.Shear(0, oElement.first[0] * 3.14 / 180.0, order);
break;
}
default: break;
}
}

View File

@ -234,6 +234,8 @@ namespace NSCSS
TransformTranslate,
TransformScale,
TransformRotate,
TransformSkewX,
TransformSkewY,
TransformNone
} TransformType;

View File

@ -1606,6 +1606,9 @@ namespace MetaFile
TPointD oPoint1(pArcTo->left, pArcTo->top), oPoint2(pArcTo->right, pArcTo->bottom);
oTransform.Apply(oPoint1.x, oPoint1.y);
oTransform.Apply(oPoint2.x, oPoint2.y);
double dXRadius = std::fabs(oPoint2.x - oPoint1.x) / 2;
double dYRadius = std::fabs(oPoint2.y - oPoint1.x) / 2;

View File

@ -458,9 +458,17 @@ namespace MetaFile
ResetClip();
TXForm *pTransform = m_pParser->GetTransform();
double dLeft = oClip.dLeft;
double dTop = oClip.dTop;
double dRight = oClip.dRight;
double dBottom = oClip.dBottom;
pTransform->Apply(dLeft, dTop);
pTransform->Apply(dRight, dBottom);
const std::wstring wsId = L"INTERSECTCLIP_" + ConvertToWString(++m_unNumberDefs, 0);
const std::wstring wsValue = L"<rect x=\"" + ConvertToWString(oClip.dLeft * pTransform->M11, 0) + L"\" y=\"" + ConvertToWString(oClip.dTop * pTransform->M22, 0) + L"\" width=\"" + ConvertToWString((oClip.dRight - oClip.dLeft) * pTransform->M11, 0) + L"\" height=\"" + ConvertToWString((oClip.dBottom - oClip.dTop) * pTransform->M22, 0) + L"\"/>";
const std::wstring wsValue = L"<rect x=\"" + ConvertToWString(dLeft, 0) + L"\" y=\"" + ConvertToWString(dTop, 0) + L"\" width=\"" + ConvertToWString(dRight - dLeft, 0) + L"\" height=\"" + ConvertToWString(dBottom - dTop, 0) + L"\"/>";
m_oClip.AddClipValue(wsId, wsValue);
}
@ -470,12 +478,28 @@ namespace MetaFile
CheckClip();
TXForm *pTransform = m_pParser->GetTransform();
double dClipLeft = oClip.dLeft;
double dClipTop = oClip.dTop;
double dClipRight = oClip.dRight;
double dClipBottom = oClip.dBottom;
pTransform->Apply(dClipLeft, dClipTop);
pTransform->Apply(dClipRight, dClipBottom);
double dBBLeft = oBB.dLeft;
double dBBTop = oBB.dTop;
double dBBRight = oBB.dRight;
double dBBBottom = oBB.dBottom;
pTransform->Apply(dBBLeft, dBBTop);
pTransform->Apply(dBBRight, dBBBottom);
const std::wstring wsId = L"EXCLUDECLIP_" + ConvertToWString(++m_unNumberDefs, 0);
const std::wstring wsValue = L"<path d=\"M" + ConvertToWString(oBB.dLeft * pTransform->M11) + L' ' + ConvertToWString(oBB.dTop * pTransform->M22) + L", L" + ConvertToWString(oBB.dRight * pTransform->M11) + L' ' + ConvertToWString(oBB.dTop * pTransform->M11) + L", " +
ConvertToWString(oBB.dRight * pTransform->M11) + L' ' + ConvertToWString(oBB.dBottom * pTransform->M22) + L", " + ConvertToWString(oBB.dLeft * pTransform->M11) + L' ' + ConvertToWString(oBB.dBottom * pTransform->M22) + L", M" +
ConvertToWString(oClip.dLeft * pTransform->M11) + L' ' + ConvertToWString(oClip.dTop * pTransform->M22) + L", L" + ConvertToWString(oClip.dRight * pTransform->M11) + L' ' + ConvertToWString(oClip.dTop * pTransform->M22) + L", " +
ConvertToWString(oClip.dRight * pTransform->M11) + L' ' + ConvertToWString(oClip.dBottom * pTransform->M22) + L", " + ConvertToWString(oClip.dLeft * pTransform->M11) + L' ' + ConvertToWString(oClip.dLeft * pTransform->M22) + L"\" clip-rule=\"evenodd\"/>";
const std::wstring wsValue = L"<path d=\"M" + ConvertToWString(dBBLeft) + L' ' + ConvertToWString(dBBTop) + L", L" + ConvertToWString(dBBRight) + L' ' + ConvertToWString(dBBTop) + L", " +
ConvertToWString(dBBRight) + L' ' + ConvertToWString(dBBBottom) + L", " + ConvertToWString(dBBLeft ) + L' ' + ConvertToWString(dBBBottom) + L", M" +
ConvertToWString(dClipLeft) + L' ' + ConvertToWString(dClipTop) + L", L" + ConvertToWString(dClipRight) + L' ' + ConvertToWString(dClipTop) + L", " +
ConvertToWString(dClipRight) + L' ' + ConvertToWString(dClipBottom) + L", " + ConvertToWString(dClipLeft) + L' ' + ConvertToWString(dClipLeft ) + L"\" clip-rule=\"evenodd\"/>";
m_oClip.AddClipValue(wsId, wsValue);
}

View File

@ -1439,6 +1439,7 @@ namespace MetaFile
if (NULL != m_pInterpretator)
{
m_pInterpretator->HANDLE_META_INTERSECTCLIPRECT(shLeft, shTop, shRight, shBottom);
m_pInterpretator->ResetClip();
m_pInterpretator->IntersectClip(oClip);
}
UpdateOutputDC();

View File

@ -126,11 +126,14 @@ bool CSvgFile::Draw(IRenderer *pRenderer, double dX, double dY, double dWidth, d
}
}
double dWindowWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel);
double dWindowHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel);
double dViewBoxWidth = oViewBox.m_oWidth.ToDouble(NSCSS::Pixel);
double dViewBoxHeight = oViewBox.m_oHeight.ToDouble(NSCSS::Pixel);
double dWindowWidth = oWindow.m_oWidth.ToDouble(NSCSS::Pixel, dViewBoxWidth);
double dWindowHeight = oWindow.m_oHeight.ToDouble(NSCSS::Pixel, dViewBoxHeight);
if (0. == dWindowWidth || 0. == dWindowHeight)
return false;
double oldTransform[6];
oldTransform[0] = oldTransform[3] = 1;

View File

@ -44,10 +44,10 @@ namespace SVG
void CCircle::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke))
nTypePath += c_nStroke;
if (Apply(pRenderer, &pStyles->m_oFill, pFile, true))
if (ApplyFill(pRenderer, &pStyles->m_oFill, pFile, true))
nTypePath += c_nWindingFillMode;
}

View File

@ -4,12 +4,18 @@ namespace SVG
{
CClipPath::CClipPath(XmlUtils::CXmlNode &oNode)
: CAppliedObject(oNode)
{}
{
if (L"userSpaceOnUse" == oNode.GetAttribute(L"gradientUnits"))
m_enUnits = ClipU_UserSpaceOnUse;
else
m_enUnits = ClipU_ObjectBoundingBox;
}
void CClipPath::SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
// SetClip(mAttributes, ushLevel, bHardMode);
// SetMask(mAttributes, ushLevel, bHardMode);
SetTransform(mAttributes, ushLevel, bHardMode);
SetClip(mAttributes, ushLevel, bHardMode);
SetMask(mAttributes, ushLevel, bHardMode);
}
bool CClipPath::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
@ -17,15 +23,11 @@ namespace SVG
if (NULL == pRenderer || NULL == pFile)
return false;
pRenderer->put_ClipMode(c_nClipRegionUnion);
pRenderer->PathCommandStart();
ApplyClip(pRenderer, &m_oTransformtaion.m_oClip, pFile, oObjectBounds);
for (const CRenderedObject* pObject : m_oContainer.m_arObjects)
pObject->Draw(pRenderer, pFile, CommandeModeClip);
pRenderer->PathCommandEnd();
return true;
}

View File

@ -5,6 +5,12 @@
namespace SVG
{
typedef enum
{
ClipU_ObjectBoundingBox,
ClipU_UserSpaceOnUse
}ClipUnits;
class CClipPath : public CAppliedObject
{
public:
@ -19,6 +25,7 @@ namespace SVG
friend class CMask;
CContainer<CRenderedObject> m_oContainer;
ClipUnits m_enUnits;
};
}

View File

@ -72,6 +72,7 @@ namespace SVG
friend class CGradient;
friend class CClipPath;
friend class CTextPath;
friend class CLinearGradient;
friend class CGraphicsContainer;
};

View File

@ -49,10 +49,10 @@ namespace SVG
void CEllipse::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke))
nTypePath += c_nStroke;
if (Apply(pRenderer, &pStyles->m_oFill, pFile, true))
if (ApplyFill(pRenderer, &pStyles->m_oFill, pFile, true))
nTypePath += c_nWindingFillMode;
}

View File

@ -38,12 +38,16 @@ namespace SVG
: CAppliedObject(oNode)
{
m_wsXlinkHref = oNode.GetAttribute(L"href", oNode.GetAttribute(L"xlink:href"));
m_oTransform.SetMatrix(oNode.GetAttribute(L"gradientTransform"), 0, true);
if (L"userSpaceOnUse" == oNode.GetAttribute(L"gradientUnits"))
m_enGradientUnits = GradU_UserSpaceOnUse;
else
m_enGradientUnits = GradU_ObjectBoundingBox;
}
void CGradient::SetData(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"transform"))
m_oTransform.SetMatrix(mAttributes.at(L"transform"), ushLevel, bHardMode);
}
bool CGradient::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
@ -58,21 +62,47 @@ namespace SVG
CGradient *pGradiend = dynamic_cast<CGradient*>(pFile->GetMarkedObject(m_wsXlinkHref));
return (NULL == pGradiend) ? false : pGradiend->Apply(pRenderer, pFile, oObjectBounds);
if (NULL == pGradiend)
return false;
pGradiend->Apply(pRenderer, pFile, oObjectBounds);
}
std::vector<LONG> arColors;
std::vector<double> arPositions;
for (const CStopElement* pStopElement : m_arObjects)
else
{
arColors.push_back(((unsigned int)(pStopElement->GetColor().ToInt() | ((unsigned char)(255. * pStopElement->GetColor().GetOpacity()) << 24))));
arPositions.push_back(pStopElement->GetOffset().ToDouble());
std::vector<LONG> arColors;
std::vector<double> arPositions;
for (const CStopElement* pStopElement : m_arObjects)
{
arColors.push_back(((unsigned int)(pStopElement->GetColor().ToInt() | ((unsigned char)(255. * pStopElement->GetColor().GetOpacity()) << 24))));
arPositions.push_back(pStopElement->GetOffset().ToDouble());
}
pRenderer->put_BrushGradientColors(arColors.data(), arPositions.data(), arColors.size());
}
pRenderer->put_BrushTransform(m_oTransform.GetMatrix().GetFinalValue());
return true;
}
void CGradient::ApplyTransform(IRenderer* pRenderer, const TBounds& oBounds, double& dAngle) const
{
TBounds oNewBounds(oBounds);
Aggplus::CMatrix oMatrix = m_oTransform.GetMatrix().GetFinalValue();
dAngle = oMatrix.rotation() * 180. / M_PI;
if (GradU_ObjectBoundingBox == m_enGradientUnits)
{
oMatrix.Scale(oBounds.m_dRight - oBounds.m_dLeft, oBounds.m_dBottom - oBounds.m_dTop, Aggplus::MatrixOrderAppend);
oMatrix.Scale(1 / (oBounds.m_dRight - oBounds.m_dLeft), 1 / (oBounds.m_dBottom - oBounds.m_dTop));
oMatrix.TransformPoint(oNewBounds.m_dLeft, oNewBounds.m_dTop);
oMatrix.TransformPoint(oNewBounds.m_dRight, oNewBounds.m_dBottom);
}
pRenderer->put_BrushGradientColors(arColors.data(), arPositions.data(), arColors.size());
return true;
pRenderer->BrushBounds(oNewBounds.m_dLeft, oNewBounds.m_dTop, oNewBounds.m_dRight - oNewBounds.m_dLeft, oNewBounds.m_dBottom - oNewBounds.m_dTop);
}
CLinearGradient::CLinearGradient(XmlUtils::CXmlNode& oNode)
@ -87,38 +117,43 @@ namespace SVG
bool CLinearGradient::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
{
if (!CGradient::Apply(pRenderer, pFile, oObjectBounds))
return false;
return false;
pRenderer->put_BrushType(c_BrushTypePathGradient1);
double dX1 = m_oX1.ToDouble(NSCSS::Pixel);
double dY1 = m_oY1.ToDouble(NSCSS::Pixel);
double dX2 = m_oX2.ToDouble(NSCSS::Pixel);
double dY2 = m_oY2.ToDouble(NSCSS::Pixel);
double dWidthKoef = 1.;
double dHeightKoef = 1.;
if (NSCSS::UnitMeasure::Percent == m_oX2.GetUnitMeasure())
dWidthKoef*= dX2 / 100.;
else if (NSCSS::UnitMeasure::None == m_oX2.GetUnitMeasure() && dX2 > 1.)
dWidthKoef = dX2;
if (NSCSS::UnitMeasure::Percent == m_oY2.GetUnitMeasure())
dHeightKoef*= dY2 / 100.;
else if (NSCSS::UnitMeasure::None == m_oY2.GetUnitMeasure() && dY2 > 1.)
dHeightKoef = dY2;
if (m_oX1 == m_oX2 && m_oY1 == m_oY2)
{
pRenderer->put_BrushType(c_BrushTypeSolid);
pRenderer->put_BrushColor1(m_arObjects.back()->GetColor().ToInt());
pRenderer->put_BrushAlpha1(m_arObjects.back()->GetOffset().ToInt());
return true;
}
double dAngle = 0.;
if (std::fabs(dX2 - dX1) >= 0. || fabs(dY2 - dY1) >= 0.)
dAngle = 180. * std::atan2(dY2 - dY1, dX2 - dX1) / M_PI;
TBounds oNewBounds(oObjectBounds);
if (GradU_ObjectBoundingBox == m_enGradientUnits)
{
oNewBounds.m_dLeft += (oObjectBounds.m_dRight - oObjectBounds.m_dLeft) * m_oX1.ToDouble(NSCSS::Pixel);
oNewBounds.m_dTop += (oObjectBounds.m_dBottom - oObjectBounds.m_dTop) * m_oY1.ToDouble(NSCSS::Pixel);
oNewBounds.m_dRight *= (!m_oX2.Zero()) ? m_oX2.ToDouble(NSCSS::Pixel) : 1.;
oNewBounds.m_dBottom *= (!m_oY2.Zero()) ? m_oY2.ToDouble(NSCSS::Pixel) : 1.;
}
else if (GradU_UserSpaceOnUse == m_enGradientUnits)
{
if (!m_oX1.Empty()) oNewBounds.m_dLeft = m_oX1.ToDouble(NSCSS::Pixel);
if (!m_oY1.Empty()) oNewBounds.m_dTop = m_oY1.ToDouble(NSCSS::Pixel);
if (!m_oX2.Empty()) oNewBounds.m_dRight = m_oX2.ToDouble(NSCSS::Pixel);
if (!m_oY2.Empty()) oNewBounds.m_dBottom = m_oY2.ToDouble(NSCSS::Pixel);
}
CGradient::ApplyTransform(pRenderer, oNewBounds, dAngle);
dAngle += 180. * std::atan2(oNewBounds.m_dBottom - oNewBounds.m_dTop, oNewBounds.m_dRight - oNewBounds.m_dLeft) / M_PI;
pRenderer->put_BrushLinearAngle(dAngle);
pRenderer->BrushBounds(oObjectBounds.m_dLeft, oObjectBounds.m_dTop, (oObjectBounds.m_dRight - oObjectBounds.m_dLeft) * dWidthKoef, (oObjectBounds.m_dBottom - oObjectBounds.m_dTop) * dHeightKoef);
Aggplus::CMatrix oMatrix(1, 0, 0, 1, 100, 0);
pRenderer->put_BrushTransform(oMatrix);
return true;
}
@ -133,16 +168,31 @@ namespace SVG
bool CRadialGradient::Apply(IRenderer *pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds)
{
if (!CGradient::Apply(pRenderer, pFile, oObjectBounds))
if (!CGradient::Apply(pRenderer, pFile, oObjectBounds) || m_oR.Zero())
return false;
double dCX = (oObjectBounds.m_dRight + oObjectBounds.m_dLeft) / 2.;
double dCY = (oObjectBounds.m_dBottom + oObjectBounds.m_dTop) / 2.;
double dR = oObjectBounds.m_dBottom - oObjectBounds.m_dTop;
if (GradU_ObjectBoundingBox == m_enGradientUnits)
{
if (!m_oCx.Empty())
dCX = oObjectBounds.m_dLeft + (oObjectBounds.m_dRight - oObjectBounds.m_dLeft) * m_oCx.ToDouble(NSCSS::Pixel);
if (!m_oCy.Empty())
dCY = oObjectBounds.m_dTop + (oObjectBounds.m_dBottom - oObjectBounds.m_dTop) * m_oCy.ToDouble(NSCSS::Pixel);
if (!m_oR.Empty())
dR = (oObjectBounds.m_dBottom - oObjectBounds.m_dTop) * m_oR.ToDouble(NSCSS::Pixel);
}
else if (GradU_UserSpaceOnUse == m_enGradientUnits)
{
if (!m_oCx.Empty()) dCX = m_oCx.ToDouble(NSCSS::Pixel);
if (!m_oCy.Empty()) dCY = m_oCy.ToDouble(NSCSS::Pixel);
if (!m_oR.Empty()) dR = m_oR .ToDouble(NSCSS::Pixel);
}
pRenderer->put_BrushType(c_BrushTypePathGradient2);
double dCx = m_oCx.ToDouble(NSCSS::Pixel) * (oObjectBounds.m_dRight - oObjectBounds.m_dLeft) + oObjectBounds.m_dLeft;
double dCy = m_oCy.ToDouble(NSCSS::Pixel) * (oObjectBounds.m_dBottom - oObjectBounds.m_dTop) + oObjectBounds.m_dTop;
double dR = m_oR .ToDouble(NSCSS::Pixel) * (oObjectBounds.m_dRight - oObjectBounds.m_dLeft);
pRenderer->BrushBounds(dCx - dR, dCy - dR, (dR != 0) ? dR * 2 : (oObjectBounds.m_dRight - oObjectBounds.m_dLeft), (dR != 0) ? dR * 2 : (oObjectBounds.m_dBottom - oObjectBounds.m_dTop));
pRenderer->BrushBounds(dCX - dR, dCY - dR, 2. * dR, 2. * dR);
return true;
}

View File

@ -8,8 +8,8 @@ namespace SVG
{
typedef enum
{
ObjectBoundingBox,
UserSpaceOnUse
GradU_ObjectBoundingBox,
GradU_UserSpaceOnUse
}GradientUnits;
typedef enum
@ -37,14 +37,16 @@ namespace SVG
class CGradient : public CContainer<CStopElement>, public CAppliedObject
{
friend class CLinearGradient;
friend class CRadialGradient;
public:
CGradient(XmlUtils::CXmlNode& oNode);
void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) override;
bool Apply(IRenderer* pRenderer, const CSvgFile *pFile, const TBounds &oObjectBounds) override;
void ApplyTransform(IRenderer *pRenderer, const TBounds& oBounds, double& dAngle) const;
private:
std::wstring m_wsXlinkHref;
GradientUnits m_enGradientUnits;
SpreadMethod m_enSpreadMethod;

View File

@ -29,7 +29,7 @@ namespace SVG
void CLine::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke, true))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke, true))
nTypePath += c_nStroke;
}
}

View File

@ -5,8 +5,6 @@ namespace SVG
{
TSvgStyles &TSvgStyles::operator+=(const TSvgStyles &oSvgStyles)
{
m_oTransform.SetMatrix(oSvgStyles.m_oTransform.GetMatrix().ToWString(), 0, false);
if (!oSvgStyles.m_oFill.Empty())
m_oFill.SetValue(L'#' + oSvgStyles.m_oFill.ToWString(), 0, false);
@ -26,15 +24,6 @@ namespace SVG
if (m_oStroke.m_oLineJoin.Empty() && !oSvgStyles.m_oStroke.m_oLineJoin.Empty())
m_oStroke.m_oLineJoin = oSvgStyles.m_oStroke.m_oLineJoin;
if (m_oClip.m_oHref.Empty() && !oSvgStyles.m_oClip.m_oHref.Empty())
m_oClip.m_oHref = oSvgStyles.m_oClip.m_oHref;
if (m_oClip.m_oRule.Empty() && !oSvgStyles.m_oClip.m_oRule.Empty())
m_oClip.m_oRule = oSvgStyles.m_oClip.m_oRule;
if (m_oMask.Empty() && !oSvgStyles.m_oMask.Empty() && NSCSS::NSProperties::ColorUrl == oSvgStyles.m_oMask.GetType())
m_oMask= oSvgStyles.m_oMask;
return *this;
}
@ -79,7 +68,110 @@ namespace SVG
SetData(NSCSS::NS_STATIC_FUNCTIONS::GetRules(wsStyles), ushLevel, bHardMode);
}
void CObject::SetTransform(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"transform"))
m_oTransformtaion.m_oTransform.SetMatrix(mAttributes.at(L"transform"), ushLevel, bHardMode);
else
m_oTransformtaion.m_oTransform.SetMatrix(L"", ushLevel, false);
}
void CObject::SetClip(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"clip-path"))
m_oTransformtaion.m_oClip.m_oHref.SetValue(mAttributes.at(L"clip-path"), ushLevel, bHardMode);
else
m_oTransformtaion.m_oClip.m_oHref.SetValue(L"", ushLevel, false);
if (mAttributes.end() != mAttributes.find(L"clip-rule"))
m_oTransformtaion.m_oClip.m_oRule.SetValue(mAttributes.at(L"clip-rule"), std::vector<std::wstring>{L"nonzero", L"evenodd"}, ushLevel, bHardMode);
}
void CObject::SetMask(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"mask"))
m_oTransformtaion.m_oMask.SetValue(mAttributes.at(L"mask"), ushLevel, bHardMode);
else
m_oTransformtaion.m_oMask.SetValue(L"", ushLevel, false);
}
void CObject::SetDisplay(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
std::wstring wsDisplay, wsVisibility;
if (mAttributes.end() != mAttributes.find(L"display"))
wsDisplay = mAttributes.at(L"display");
if (mAttributes.end() != mAttributes.find(L"visibility"))
wsVisibility = mAttributes.at(L"visibility");
if (L"none" == wsDisplay || L"hidden" == wsVisibility || L"collapse" == wsVisibility)
m_oTransformtaion.m_bDraw = false;
else
m_oTransformtaion.m_bDraw = true;
}
bool CObject::ApplyTransform(IRenderer *pRenderer, const NSCSS::NSProperties::CTransform *pTransform, Aggplus::CMatrix& oOldMatrix) const
{
if (NULL == pRenderer || NULL == pTransform)
return false;
double dM11, dM12, dM21, dM22, dRx, dRy;
pRenderer->GetTransform(&dM11, &dM12, &dM21, &dM22, &dRx, &dRy);
oOldMatrix.SetElements(dM11, dM12, dM21, dM22, dRx, dRy);
Aggplus::CMatrix oMatrix(oOldMatrix);
pTransform->GetMatrix().ApplyTranform(oMatrix);
pRenderer->SetTransform(oMatrix.sx(), oMatrix.shy(), oMatrix.shx(), oMatrix.sy(), oMatrix.tx(), oMatrix.ty());
return true;
}
bool CObject::ApplyClip(IRenderer *pRenderer, const TClip *pClip, const CSvgFile *pFile, const TBounds &oBounds) const
{
if (NULL == pRenderer || NULL == pClip || NULL == pFile)
return false;
if (pClip->m_oRule == L"evenodd")
pRenderer->put_ClipMode(c_nClipRegionTypeEvenOdd);
else
pRenderer->put_ClipMode(c_nClipRegionTypeWinding);
if (pClip->m_oHref.Empty() || NSCSS::NSProperties::ColorType::ColorUrl != pClip->m_oHref.GetType())
return true;
pRenderer->BeginCommand(c_nResetClipType);
pRenderer->EndCommand(c_nResetClipType);
return ApplyDef(pRenderer, pFile, pClip->m_oHref.ToWString(), oBounds);
}
bool CObject::ApplyMask(IRenderer *pRenderer, const NSCSS::NSProperties::CColor *pMask, const CSvgFile *pFile, const TBounds &oBounds) const
{
if (NULL == pRenderer || NULL == pMask || NULL == pFile || NSCSS::NSProperties::ColorType::ColorUrl != pMask->GetType())
return false;
return ApplyDef(pRenderer, pFile, pMask->ToWString(), oBounds);
}
bool CObject::ApplyDef(IRenderer *pRenderer, const CSvgFile *pFile, const std::wstring &wsUrl, const TBounds &oBounds) const
{
if (NULL == pRenderer || NULL == pFile || wsUrl.empty())
return false;
CAppliedObject *pDefObject = dynamic_cast<CAppliedObject*>(pFile->GetMarkedObject(wsUrl));
if (NULL == pDefObject)
return false;
return pDefObject->Apply(pRenderer, pFile, oBounds);
}
std::wstring CObject::GetId() const
{
return m_oXmlNode.m_wsId;
@ -138,7 +230,7 @@ namespace SVG
m_oStyles.m_oStroke.m_oMiterlimit = 4.;
m_oStyles.m_bDraw = true;
m_oTransformtaion.m_bDraw = true;
}
void CRenderedObject::SetStroke(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
@ -180,63 +272,17 @@ namespace SVG
m_oStyles.m_oFill.SetOpacity(mAttributes.at(L"opacity"), ushLevel, bHardMode);
}
void CRenderedObject::SetTransform(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"transform"))
m_oStyles.m_oTransform.SetMatrix(mAttributes.at(L"transform"), ushLevel, bHardMode);
else
m_oStyles.m_oTransform.SetMatrix(L"", ushLevel, false);
}
void CRenderedObject::SetClip(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"clip-path"))
m_oStyles.m_oClip.m_oHref.SetValue(mAttributes.at(L"clip-path"), ushLevel, bHardMode);
else
m_oStyles.m_oClip.m_oHref.SetValue(L"", ushLevel, false);
if (mAttributes.end() != mAttributes.find(L"clip-rule"))
m_oStyles.m_oClip.m_oRule.SetValue(mAttributes.at(L"clip-rule"), std::vector<std::wstring>{L"nonzero", L"evenodd"}, ushLevel, bHardMode);
}
void CRenderedObject::SetMask(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
if (mAttributes.end() != mAttributes.find(L"mask"))
m_oStyles.m_oMask.SetValue(mAttributes.at(L"mask"), ushLevel, bHardMode);
else
m_oStyles.m_oMask.SetValue(L"", ushLevel, false);
}
void CRenderedObject::SetDisplay(const std::map<std::wstring, std::wstring> &mAttributes, unsigned short ushLevel, bool bHardMode)
{
std::wstring wsDisplay, wsVisibility;
if (mAttributes.end() != mAttributes.find(L"display"))
wsDisplay = mAttributes.at(L"display");
if (mAttributes.end() != mAttributes.find(L"visibility"))
wsVisibility = mAttributes.at(L"visibility");
if (L"none" == wsDisplay || L"hidden" == wsVisibility || L"collapse" == wsVisibility)
m_oStyles.m_bDraw = false;
else
m_oStyles.m_bDraw = true;
}
bool CRenderedObject::StartPath(IRenderer *pRenderer, const CSvgFile *pFile, Aggplus::CMatrix &oOldTransform, CommandeMode oMode) const
{
if (NULL == pRenderer || !m_oStyles.m_bDraw)
if (NULL == pRenderer || !m_oTransformtaion.m_bDraw)
return false;
Apply(pRenderer, &m_oStyles.m_oTransform, oOldTransform);
Apply(pRenderer, &m_oStyles.m_oClip, pFile);
ApplyMask(pRenderer, &m_oStyles.m_oMask, pFile);
ApplyTransform(pRenderer, &m_oTransformtaion.m_oTransform, oOldTransform);
ApplyClip(pRenderer, &m_oTransformtaion.m_oClip, pFile, GetBounds());
ApplyMask(pRenderer, &m_oTransformtaion.m_oMask, pFile, GetBounds());
if (CommandeModeClip == oMode)
{
pRenderer->BeginCommand(c_nClipType);
return true;
}
pRenderer->BeginCommand(c_nPathType);
pRenderer->PathCommandStart();
@ -249,6 +295,8 @@ namespace SVG
if (CommandeModeClip == oMode)
{
pRenderer->EndCommand(c_nClipType);
pRenderer->EndCommand(c_nPathType);
pRenderer->PathCommandEnd();
pRenderer->SetTransform(oOldTransform.sx(), oOldTransform.shy(), oOldTransform.shx(), oOldTransform.sy(), oOldTransform.tx(), oOldTransform.ty());
return;
}
@ -268,13 +316,13 @@ namespace SVG
pRenderer->EndCommand(c_nPathType);
pRenderer->PathCommandEnd();
if (!m_oStyles.m_oClip.m_oHref.Empty())
if (!m_oTransformtaion.m_oClip.m_oHref.Empty())
{
pRenderer->BeginCommand(c_nResetClipType);
pRenderer->EndCommand(c_nResetClipType);
}
if (!m_oStyles.m_oMask.Empty())
if (!m_oTransformtaion.m_oMask.Empty())
{
pRenderer->BeginCommand(c_nResetMaskType);
pRenderer->EndCommand(c_nResetMaskType);
@ -286,7 +334,7 @@ namespace SVG
void CRenderedObject::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{}
bool CRenderedObject::Apply(IRenderer *pRenderer, const TStroke *pStroke, bool bUseDefault) const
bool CRenderedObject::ApplyStroke(IRenderer *pRenderer, const TStroke *pStroke, bool bUseDefault) const
{
if (NULL == pRenderer || NULL == pStroke || NSCSS::NSProperties::ColorType::ColorNone == pStroke->m_oColor.GetType() || (!bUseDefault && ((pStroke->m_oWidth.Empty() || pStroke->m_oWidth.Zero()) && pStroke->m_oColor.Empty())))
{
@ -325,7 +373,7 @@ namespace SVG
return true;
}
bool CRenderedObject::Apply(IRenderer *pRenderer, const NSCSS::NSProperties::CColor *pFill, const CSvgFile *pFile, bool bUseDefault) const
bool CRenderedObject::ApplyFill(IRenderer *pRenderer, const NSCSS::NSProperties::CColor *pFill, const CSvgFile *pFile, bool bUseDefault) const
{
if (NULL == pRenderer || NULL == pFill || NSCSS::NSProperties::ColorType::ColorNone == pFill->GetType() || (!bUseDefault && pFill->Empty()))
{
@ -340,7 +388,7 @@ namespace SVG
}
else if (NSCSS::NSProperties::ColorType::ColorUrl == pFill->GetType())
{
if (!ApplyDef(pRenderer, pFile, pFill->ToWString()))
if (!ApplyDef(pRenderer, pFile, pFill->ToWString(), GetBounds()))
{
if (bUseDefault)
{
@ -362,63 +410,6 @@ namespace SVG
return true;
}
bool CRenderedObject::Apply(IRenderer *pRenderer, const NSCSS::NSProperties::CTransform *pTransform, Aggplus::CMatrix& oOldMatrix) const
{
if (NULL == pRenderer || NULL == pTransform)
return false;
double dM11, dM12, dM21, dM22, dRx, dRy;
pRenderer->GetTransform(&dM11, &dM12, &dM21, &dM22, &dRx, &dRy);
oOldMatrix.SetElements(dM11, dM12, dM21, dM22, dRx, dRy);
Aggplus::CMatrix oMatrix(oOldMatrix);
pTransform->GetMatrix().ApplyTranform(oMatrix);
pRenderer->SetTransform(oMatrix.sx(), oMatrix.shy(), oMatrix.shx(), oMatrix.sy(), oMatrix.tx(), oMatrix.ty());
return true;
}
bool CRenderedObject::Apply(IRenderer *pRenderer, const TClip *pClip, const CSvgFile *pFile) const
{
if (NULL == pRenderer || NULL == pClip || NULL == pFile)
return false;
if (pClip->m_oRule == L"evenodd")
pRenderer->put_ClipMode(c_nClipRegionTypeEvenOdd);
else
pRenderer->put_ClipMode(c_nClipRegionTypeWinding);
if (pClip->m_oHref.Empty() || NSCSS::NSProperties::ColorType::ColorUrl != pClip->m_oHref.GetType())
return true;
return ApplyDef(pRenderer, pFile, pClip->m_oHref.ToWString());
}
bool CRenderedObject::ApplyMask(IRenderer *pRenderer, const NSCSS::NSProperties::CColor *pMask, const CSvgFile *pFile) const
{
if (NULL == pRenderer || NULL == pMask || NULL == pFile || NSCSS::NSProperties::ColorType::ColorUrl != pMask->GetType())
return false;
return ApplyDef(pRenderer, pFile, pMask->ToWString());
}
bool CRenderedObject::ApplyDef(IRenderer *pRenderer, const CSvgFile *pFile, const std::wstring &wsUrl) const
{
if (NULL == pRenderer || NULL == pFile || wsUrl.empty())
return false;
CAppliedObject *pDefObject = dynamic_cast<CAppliedObject*>(pFile->GetMarkedObject(wsUrl));
if (NULL == pDefObject)
return false;
return pDefObject->Apply(pRenderer, pFile, GetBounds());
}
CAppliedObject::CAppliedObject(XmlUtils::CXmlNode &oNode)
: CObject(oNode)
{}

View File

@ -15,12 +15,16 @@ namespace SVG
{
SvgColor m_oFill;
TStroke m_oStroke;
TSvgStyles& operator+=(const TSvgStyles& oSvgStyles);
};
struct TSvgTransformation
{
SvgTransform m_oTransform;
TClip m_oClip;
SvgColor m_oMask;
bool m_bDraw;
TSvgStyles& operator+=(const TSvgStyles& oSvgStyles);
};
enum ObjectType
@ -42,11 +46,23 @@ namespace SVG
virtual void SetData(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false) = 0;
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);
void SetDisplay(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
std::wstring GetId() const;
virtual std::vector<NSCSS::CNode> GetFullPath() const;
private:
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;
@ -60,7 +76,10 @@ namespace SVG
friend class CEllipse;
friend class CPolyline;
NSCSS::CNode m_oXmlNode;
friend class CClipPath;
NSCSS::CNode m_oXmlNode;
TSvgTransformation m_oTransformtaion;
};
enum CommandeMode
@ -91,23 +110,14 @@ namespace SVG
void SetStroke(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
void SetFill(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
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);
void SetDisplay(const std::map<std::wstring, std::wstring>& mAttributes, unsigned short ushLevel, bool bHardMode = false);
bool StartPath(IRenderer* pRenderer, const CSvgFile *pFile, Aggplus::CMatrix& oOldTransform, CommandeMode oMode = CommandeModeDraw) const;
void EndPath(IRenderer* pRenderer, const CSvgFile *pFile, const Aggplus::CMatrix& oOldTransform, CommandeMode oMode = CommandeModeDraw, const TSvgStyles* pOtherStyles = NULL) const;
virtual void ApplyStyle(IRenderer* pRenderer, const TSvgStyles* pStyles, const CSvgFile *pFile, int& nTypePath) const;
bool Apply(IRenderer* pRenderer, const TStroke* pStroke, bool bUseDefault = false) const;
bool Apply(IRenderer* pRenderer, const SvgColor* pFill, const CSvgFile *pFile, bool bUseDefault = false) const;
bool Apply(IRenderer* pRenderer, const SvgTransform* pTransform, Aggplus::CMatrix& oOldMatrix) const;
bool Apply(IRenderer* pRenderer, const TClip* pClip, const CSvgFile *pFile) const;
bool ApplyMask(IRenderer* pRenderer, const SvgColor* pMask, const CSvgFile *pFile) const;
bool ApplyDef(IRenderer* pRenderer, const CSvgFile *pFile, const std::wstring& wsUrl) const;
bool ApplyStroke(IRenderer* pRenderer, const TStroke* pStroke, bool bUseDefault = false) const;
bool ApplyFill(IRenderer* pRenderer, const SvgColor* pFill, const CSvgFile *pFile, bool bUseDefault = false) const;
friend class CUse;
friend class CLine;

View File

@ -474,10 +474,10 @@ namespace SVG
void CPath::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke))
nTypePath += c_nStroke;
if (Apply(pRenderer, &pStyles->m_oFill, pFile))
if (ApplyFill(pRenderer, &pStyles->m_oFill, pFile, true))
nTypePath += (m_bEvenOddRule) ? c_nEvenOddFillMode : c_nWindingFillMode;
}

View File

@ -15,6 +15,11 @@ namespace SVG
m_oRx.SetValue(oNode.GetAttribute(L"rx"));
m_oRy.SetValue(oNode.GetAttribute(L"ry"));
if (m_oRx.Empty() && !m_oRy.Empty())
m_oRx = m_oRy;
else if (!m_oRx.Empty() && m_oRy.Empty())
m_oRy = m_oRx;
}
CRect::~CRect()
@ -82,10 +87,10 @@ namespace SVG
void CRect::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke))
nTypePath += c_nStroke;
if (Apply(pRenderer, &pStyles->m_oFill, pFile, true))
if (ApplyFill(pRenderer, &pStyles->m_oFill, pFile, true))
nTypePath += c_nWindingFillMode;
}

View File

@ -158,12 +158,11 @@ namespace SVG
});
}
pSvgObject->SetData(arSelectors[i].m_mAttributes, i + 1);
pSvgObject->SetData(arSelectors[i].m_wsStyle, i + 1, true);
for (const NSCSS::CElement* oElement : arFindElements)
pSvgObject->SetData(oElement->GetStyle(), i + 1);
pSvgObject->SetData(arSelectors[i].m_mAttributes, i + 1);
}
}
}

View File

@ -181,10 +181,10 @@ namespace SVG
void CTSpan::ApplyStyle(IRenderer *pRenderer, const TSvgStyles *pStyles, const CSvgFile *pFile, int &nTypePath) const
{
if (Apply(pRenderer, &pStyles->m_oStroke, true))
if (ApplyStroke(pRenderer, &pStyles->m_oStroke, true))
nTypePath += c_nStroke;
if (Apply(pRenderer, &pStyles->m_oFill, pFile, true))
if (ApplyFill(pRenderer, &pStyles->m_oFill, pFile, true))
nTypePath += c_nWindingFillMode;
}
@ -371,7 +371,7 @@ namespace SVG
if (NULL == pRenderer)
return;
Aggplus::CMatrix oCurrentMatrix(m_oStyles.m_oTransform.GetMatrix().GetFinalValue(NSCSS::NSProperties::TransformRotate));
Aggplus::CMatrix oCurrentMatrix(m_oTransformtaion.m_oTransform.GetMatrix().GetFinalValue(NSCSS::NSProperties::TransformRotate));
double dXScale = 1., dYScale = 1.;

View File

@ -27,7 +27,7 @@ namespace SVG
bool CUse::Draw(IRenderer *pRenderer, const CSvgFile *pFile, CommandeMode oMode, const TSvgStyles* pOtherStyles) const
{
if (NULL == pRenderer || !m_oStyles.m_bDraw)
if (NULL == pRenderer || !m_oTransformtaion.m_bDraw)
return false;
double dM11, dM12, dM21, dM22, dRx, dRy;