diff options
author | Thorsten Behrens <tbehrens@novell.com> | 2011-06-21 09:11:28 +0200 |
---|---|---|
committer | Fridrich Štrba <fridrich.strba@bluewin.ch> | 2011-06-22 12:55:16 +0200 |
commit | b036162d609b01e7b27e0eafc09cbd0192d95200 (patch) | |
tree | 6fe364b210c7a87fa753c101824594084a026be4 /xmloff | |
parent | 4f314412dee35856ae70a8331047f7c54e07073b (diff) |
Teach LibreOffice proper svg:d support
Diffstat (limited to 'xmloff')
-rw-r--r-- | xmloff/inc/xexptran.hxx | 12 | ||||
-rw-r--r-- | xmloff/source/draw/xexptran.cxx | 990 |
2 files changed, 48 insertions, 954 deletions
diff --git a/xmloff/inc/xexptran.hxx b/xmloff/inc/xexptran.hxx index bd2c55d6557e..5fbd83500be6 100644 --- a/xmloff/inc/xexptran.hxx +++ b/xmloff/inc/xexptran.hxx @@ -30,11 +30,10 @@ #define _XEXPTRANSFORM_HXX #include <rtl/ustring.hxx> -#include <com/sun/star/drawing/PointSequenceSequence.hpp> +#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp> #include <com/sun/star/drawing/PointSequence.hpp> -#include <com/sun/star/awt/Size.hpp> -#include <com/sun/star/drawing/FlagSequenceSequence.hpp> #include <com/sun/star/drawing/FlagSequence.hpp> +#include <com/sun/star/awt/Size.hpp> #include <com/sun/star/drawing/HomogenMatrix.hpp> #include <tools/mapunit.hxx> @@ -173,8 +172,7 @@ class SdXMLImExSvgDElement sal_Int32 mnLastX; sal_Int32 mnLastY; - com::sun::star::drawing::PointSequenceSequence maPoly; - com::sun::star::drawing::FlagSequenceSequence maFlag; + com::sun::star::drawing::PolyPolygonBezierCoords maPoly; public: SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox); @@ -194,8 +192,8 @@ public: const rtl::OUString& GetExportString() const { return msString; } bool IsClosed() const { return mbIsClosed; } bool IsCurve() const { return mbIsCurve; } - const com::sun::star::drawing::PointSequenceSequence& GetPointSequenceSequence() const { return maPoly; } - const com::sun::star::drawing::FlagSequenceSequence& GetFlagSequenceSequence() const { return maFlag; } + const com::sun::star::drawing::PointSequenceSequence& GetPointSequenceSequence() const { return maPoly.Coordinates; } + const com::sun::star::drawing::FlagSequenceSequence& GetFlagSequenceSequence() const { return maPoly.Flags; } }; diff --git a/xmloff/source/draw/xexptran.cxx b/xmloff/source/draw/xexptran.cxx index 0834ea1218ec..a36e8e703f82 100644 --- a/xmloff/source/draw/xexptran.cxx +++ b/xmloff/source/draw/xexptran.cxx @@ -37,6 +37,9 @@ #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/tuple/b3dtuple.hxx> #include <basegfx/matrix/b3dhommatrix.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/tools/unotools.hxx> #include <tools/string.hxx> using ::rtl::OUString; @@ -53,7 +56,19 @@ using namespace ::com::sun::star; // Predeclarations void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen); -void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection); +void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection) +{ + const sal_Int32 nLen1(FRound(aVec1.getLength())); + const sal_Int32 nLen2(FRound(aVec2.getLength())); + aVec1.normalize(); + aVec2.normalize(); + aVec1 += aVec2; + const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0))); + + bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL); + bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL); +} + ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -1520,8 +1535,7 @@ SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox) mbIsCurve( false ), mnLastX( 0L ), mnLastY( 0L ), - maPoly( 0L ), - maFlag( 0L ) + maPoly() { } @@ -1583,6 +1597,8 @@ void SdXMLImExSvgDElement::AddPolygon( const awt::Size& rObjectSize, bool bClosed, bool bRelative) { + // Leaving the export stuff for the while, should eventually also + // consolidated with basegfx svg support DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)"); sal_Int32 nCnt(pPoints->getLength()); @@ -2151,964 +2167,44 @@ void SdXMLImExSvgDElement::AddPolygon( } } -// #100617# Linear double reader -double Imp_ImportDoubleAndSpaces( - double fRetval, const OUString& rStr, sal_Int32& rPos, - const sal_Int32 nLen, const SvXMLUnitConverter& rConv) -{ - fRetval = Imp_GetDoubleChar(rStr, rPos, nLen, rConv, fRetval); - Imp_SkipSpacesAndCommas(rStr, rPos, nLen); - return fRetval; -} - -// #100617# Allow to read doubles, too. This will need to be changed to -// the usage of Imp_ImportDoubleAndSpaces(...). For now, this is sufficient -// since the interface cannot transport doubles. -sal_Int32 Imp_ImportNumberAndSpaces( - sal_Int32 nRetval, const OUString& rStr, sal_Int32& rPos, - const sal_Int32 nLen, const SvXMLUnitConverter& rConv) -{ - nRetval = FRound(Imp_ImportDoubleAndSpaces(double(nRetval), rStr, rPos, nLen, rConv)); - Imp_SkipSpacesAndCommas(rStr, rPos, nLen); - return nRetval; -} - -void Imp_PrepareCoorImport(sal_Int32& nX, sal_Int32& nY, - const awt::Point& rObjectPos, const awt::Size& rObjectSize, - const SdXMLImExViewBox& rViewBox, const bool bScale, const bool bTranslate) -{ - if(bTranslate) - { - nX -= rViewBox.GetX(); - nY -= rViewBox.GetY(); - } - - if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight()) - { - nX = (nX * rObjectSize.Width) / rViewBox.GetWidth(); - nY = (nY * rObjectSize.Height) / rViewBox.GetHeight(); - } - - nX += rObjectPos.X; - nY += rObjectPos.Y; -} - -void Imp_AddExportPoints(sal_Int32 nX, sal_Int32 nY, - awt::Point* pPoints, drawing::PolygonFlags* pFlags, - const sal_Int32 nInnerIndex, - drawing::PolygonFlags eFlag) -{ - if(pPoints) - pPoints[nInnerIndex] = awt::Point( nX, nY ); - - if(pFlags) - pFlags[nInnerIndex] = eFlag; -} - -void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection) -{ - const sal_Int32 nLen1(FRound(aVec1.getLength())); - const sal_Int32 nLen2(FRound(aVec2.getLength())); - aVec1.normalize(); - aVec2.normalize(); - aVec1 += aVec2; - const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0))); - - bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL); - bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL); -} - -void Imp_CorrectPolygonFlag(const sal_uInt32 nInnerIndex, const awt::Point* const pInnerSequence, - drawing::PolygonFlags* const pInnerFlags, const sal_Int32 nX1, const sal_Int32 nY1) -{ - if(nInnerIndex) - { - const awt::Point aPPrev1 = pInnerSequence[nInnerIndex - 1]; - - if(nInnerIndex > 1) - { - const awt::Point aPPrev2 = pInnerSequence[nInnerIndex - 2]; - const drawing::PolygonFlags aFPrev2 = pInnerFlags[nInnerIndex - 2]; - ::basegfx::B2DVector aVec1(aPPrev2.X - aPPrev1.X, aPPrev2.Y - aPPrev1.Y); - ::basegfx::B2DVector aVec2(nX1 - aPPrev1.X, nY1 - aPPrev1.Y); - bool bSameLength(false); - bool bSameDirection(false); - - // get vector values - Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection); - - if(drawing::PolygonFlags_CONTROL == aFPrev2) - { - // point before is a control point - if(bSameDirection) - { - if(bSameLength) - { - // set to PolygonFlags_SYMMETRIC - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC; - } - else - { - // set to PolygonFlags_SMOOTH - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; - } - } - else - { - // set to PolygonFlags_NORMAL - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; - } - } - else - { - // point before is a simple curve point - if(bSameDirection) - { - // set to PolygonFlags_SMOOTH - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; - } - else - { - // set to PolygonFlags_NORMAL - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; - } - } - } - else - { - // no point before starpoint, set type to PolygonFlags_NORMAL - pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; - } - } -} - SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew, const SdXMLImExViewBox& rViewBox, const awt::Point& rObjectPos, const awt::Size& rObjectSize, - const SvXMLUnitConverter& rConv) + const SvXMLUnitConverter& /*rConv*/) : msString( rNew ), mrViewBox( rViewBox ), mbIsClosed( false ), mbIsCurve( false ), mnLastX( 0L ), mnLastY( 0L ), - maPoly( 0L ), - maFlag( 0L ) + maPoly() { // convert string to polygon - const OUString aStr(msString.getStr(), msString.getLength()); - const sal_Int32 nLen(aStr.getLength()); - sal_Int32 nPos(0); - sal_Int32 nNumPolys(0L); - bool bEllipticalArc(false); - - // object size and ViewBox size different? - bool bScale(rObjectSize.Width != mrViewBox.GetWidth() - || rObjectSize.Height != mrViewBox.GetHeight()); - bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L); - - // first loop: count polys and get flags - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen) - { - switch(aStr[nPos++]) - { - case 'Z' : - case 'z' : - { - break; - } - case 'M' : - case 'm' : - { - nNumPolys++; - break; - } - case 'S' : - case 's' : - case 'C' : - case 'c' : - case 'Q' : - case 'q' : - case 'T' : - case 't' : - { - mbIsCurve = true; - break; - } - case 'L' : - case 'l' : - case 'H' : - case 'h' : - case 'V' : - case 'v' : - { - // normal, interpreted values. All okay. - break; - } - case 'A' : - case 'a' : - { - // Not yet interpreted value. - bEllipticalArc = true; - break; - } - } - } - - DBG_ASSERT(!bEllipticalArc, "XMLIMP: non-interpreted tags in svg:d element!"); - (void)bEllipticalArc; - - if(nNumPolys) - { - // alloc arrays - maPoly.realloc(nNumPolys); - if(IsCurve()) - maFlag.realloc(nNumPolys); - - // get outer sequences - drawing::PointSequence* pOuterSequence = maPoly.getArray(); - drawing::FlagSequence* pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L; - - // prepare new loop, count - sal_uInt32 nPointCount(0L); - nPos = 0; - Imp_SkipSpaces(aStr, nPos, nLen); - - // #104076# reset closed flag for next to be started polygon - mbIsClosed = false; - - while(nPos < nLen) - { - switch(aStr[nPos]) - { - case 'z' : - case 'Z' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - // #104076# remember closed state of current polygon - mbIsClosed = true; - - break; - } - case 'm' : - case 'M' : - { - // new poly starts, end-process current poly - if(nPointCount) - { - // #104076# If this partial polygon is closed, use one more point - // to represent that - if(mbIsClosed) - { - nPointCount++; - } - - pOuterSequence->realloc(nPointCount); - pOuterSequence++; - - if(pOuterFlags) - { - pOuterFlags->realloc(nPointCount); - pOuterFlags++; - } - - // reset point count for next polygon - nPointCount = 0L; - } - - // #104076# reset closed flag for next to be started polygon - mbIsClosed = false; - - // NO break, continue in next case - } - case 'L' : - case 'l' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - nPointCount++; - } - break; - } - case 'H' : - case 'h' : - case 'V' : - case 'v' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - nPointCount++; - } - break; - } - case 'S' : - case 's' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - nPointCount += 3; - } - break; - } - case 'C' : - case 'c' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - nPointCount += 3; - } - break; - } - - // #100617# quadratic beziers, supported as cubic ones - case 'Q' : - case 'q' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - - // use three points since quadratic is imported as cubic - nPointCount += 3; - } - break; - } - - // #100617# relative quadratic beziers, supported as cubic ones - case 'T' : - case 't' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - - // use three points since quadratic is imported as cubic - nPointCount += 3; - } - break; - } - - // #100617# not yet supported: elliptical arc - case 'A' : - case 'a' : - { - OSL_FAIL("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!"); - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - } - break; - } - - default: - { - nPos++; - OSL_FAIL("XMLIMP: non-interpreted tags in svg:d element (unknown)!"); - break; - } - } - } - - // alloc last poly (when points used) - if(nPointCount) - { - // #104076# If this partial polygon is closed, use one more point - // to represent that - if(mbIsClosed) - { - nPointCount++; - } - - pOuterSequence->realloc(nPointCount); - pOuterSequence++; - - if(pOuterFlags) - { - pOuterFlags->realloc(nPointCount); - pOuterFlags++; - } - } - - // set pointers back - pOuterSequence = maPoly.getArray(); - pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L; - awt::Point* pNotSoInnerSequence = 0L; - drawing::PolygonFlags* pNotSoInnerFlags = 0L; - sal_uInt32 nInnerIndex(0L); - - // prepare new loop, read points - nPos = 0; - Imp_SkipSpaces(aStr, nPos, nLen); - - // #104076# reset closed flag for next to be started polygon - mbIsClosed = false; - - while(nPos < nLen) - { - bool bRelative(false); - - switch(aStr[nPos]) - { - case 'z' : - case 'Z' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - // #104076# remember closed state of current polygon - mbIsClosed = true; - - break; - } - - case 'm' : - { - bRelative = true; - } - case 'M' : - { - // #104076# end-process current poly - if(mbIsClosed) - { - if(pNotSoInnerSequence) - { - // closed: add first point again - sal_Int32 nX(pNotSoInnerSequence[0].X); - sal_Int32 nY(pNotSoInnerSequence[0].Y); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - - // reset closed flag for next to be started polygon - mbIsClosed = false; - } - - // next poly - pNotSoInnerSequence = pOuterSequence->getArray(); - pOuterSequence++; - - if(pOuterFlags) - { - pNotSoInnerFlags = pOuterFlags->getArray(); - pOuterFlags++; - } - - nInnerIndex = 0L; - - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform and add point and flag - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - break; - } - - case 'l' : - { - bRelative = true; - } - case 'L' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform and add point and flag - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - break; - } - - case 'h' : - { - bRelative = true; - } - case 'H' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(mnLastY); - - if(bRelative) - nX += mnLastX; - - // set last position - mnLastX = nX; - - // calc transform and add point and flag - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - break; - } - - case 'v' : - { - bRelative = true; - } - case 'V' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX(mnLastX); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - nY += mnLastY; - - // set last position - mnLastY = nY; - - // calc transform and add point and flag - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - break; - } - - case 's' : - { - bRelative = true; - } - case 'S' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX1; - sal_Int32 nY1; - sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nX2 += mnLastX; - nY2 += mnLastY; - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform for new points - Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - - // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC - // and the Point X1,Y1 can be constructed by mirroring the point before it. - nX1 = nX2; - nY1 = nY2; - if(nInnerIndex) - { - awt::Point aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1]; - - if(nInnerIndex > 1) - { - awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2]; - nX1 = aPPrev1.X -(aPPrev2.X - aPPrev1.X); - nY1 = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y); - } - - // set curve point to symmetric - pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC; - } - - // add calculated control point - Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - - // add new points and set flags - Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); - } - break; - } + basegfx::B2DPolyPolygon aPoly; + basegfx::tools::importFromSvgD(aPoly,msString); - case 'c' : - { - bRelative = true; - } - case 'C' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nX1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nX1 += mnLastX; - nY1 += mnLastY; - nX2 += mnLastX; - nY2 += mnLastY; - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform for new points - Imp_PrepareCoorImport(nX1, nY1, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - - // correct polygon flag for previous point - Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); - - // add new points and set flags - Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); - } - break; - } - - // #100617# quadratic beziers are imported as cubic - case 'q' : - { - bRelative = true; - } - case 'Q' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nXX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nYY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nXX += mnLastX; - nYY += mnLastY; - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform for new points - Imp_PrepareCoorImport(nXX, nYY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - - // calculate X1,X2 - awt::Point aPPrev1 = (nInnerIndex) ? pNotSoInnerSequence[nInnerIndex-1] : pNotSoInnerSequence[0]; - sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0); - sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0); - sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0); - sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0); - - // correct polygon flag for previous point - Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); - - // add new points and set flags - Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); - } - break; - } - - // #100617# relative quadratic beziers are imported as cubic - case 't' : - { - bRelative = true; - } - case 'T' : - { - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); + mbIsCurve = aPoly.areControlPointsUsed(); + mbIsClosed = aPoly.isClosed(); - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - sal_Int32 nXX; - sal_Int32 nYY; - sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); - - if(bRelative) - { - nX += mnLastX; - nY += mnLastY; - } - - // set last position - mnLastX = nX; - mnLastY = nY; - - // calc transform for new points - Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); - - // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC - // and the Point X1,Y1 can be constructed by mirroring the point before it. - nXX = nX; - nYY = nY; - awt::Point aPPrev1 = pNotSoInnerSequence[0]; - - if(nInnerIndex) - { - aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1]; - - if(nInnerIndex > 1) - { - awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2]; - nXX = aPPrev1.X -(aPPrev2.X - aPPrev1.X); - nYY = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y); - } - - // set curve point to smooth here, since length - // is changed and thus only c1 can be used. - pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; - } - - // calculate X1,X2 - sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0); - sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0); - sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0); - sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0); - - // correct polygon flag for previous point - Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); - - // add new points and set flags - Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); - } - break; - } - - // #100617# not yet supported: elliptical arc - case 'A' : - case 'a' : - { - OSL_FAIL("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!"); - nPos++; - Imp_SkipSpaces(aStr, nPos, nLen); - - while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) - { - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); - } - break; - } - - default: - { - nPos++; - OSL_FAIL("XMLIMP: non-interpreted tags in svg:d element (unknown)!"); - break; - } - } - } - - // #104076# end-process closed state of last poly - if(mbIsClosed) - { - if(pNotSoInnerSequence) - { - // closed: add first point again - sal_Int32 nX(pNotSoInnerSequence[0].X); - sal_Int32 nY(pNotSoInnerSequence[0].Y); - Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); - } - } - - // #87202# If it's a curve and it's closed the last point maybe too much - // and just exported since SVG does not allow special handling of same - // start and end point, remove this last point. - // Evtl. correct the last curve flags, too. - if(IsCurve() && IsClosed()) - { - // make one more loop over the PolyPolygon - pOuterSequence = maPoly.getArray(); - pOuterFlags = maFlag.getArray(); - sal_Int32 nOuterCnt(maPoly.getLength()); - - for(sal_Int32 a(0); a < nOuterCnt; a++) - { - // get Polygon pointers - awt::Point* pInnerSequence = pOuterSequence->getArray(); - drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray(); - sal_Int32 nInnerCnt(pOuterSequence->getLength()); - - while( nInnerCnt >= 2 - && ((pInnerSequence + (nInnerCnt - 2))->X == (pInnerSequence + (nInnerCnt - 1))->X) - && ((pInnerSequence + (nInnerCnt - 2))->Y == (pInnerSequence + (nInnerCnt - 1))->Y) - && drawing::PolygonFlags_CONTROL != *(pInnerFlags + (nInnerCnt - 2))) - { - // remove last point from array - pOuterSequence->realloc(nInnerCnt - 1); - pOuterFlags->realloc(nInnerCnt - 1); - - // get new pointers - pInnerSequence = pOuterSequence->getArray(); - pInnerFlags = pOuterFlags->getArray(); - nInnerCnt = pOuterSequence->getLength(); - } - - // now evtl. correct the last curve flags - if(nInnerCnt >= 4) - { - if( pInnerSequence->X == (pInnerSequence + (nInnerCnt - 1))->X - && pInnerSequence->Y == (pInnerSequence + (nInnerCnt - 1))->Y - && drawing::PolygonFlags_CONTROL == *(pInnerFlags + 1) - && drawing::PolygonFlags_CONTROL == *(pInnerFlags + (nInnerCnt - 2))) - { - awt::Point aPrev = *(pInnerSequence + (nInnerCnt - 2)); - awt::Point aCurr = *pInnerSequence; - awt::Point aNext = *(pInnerSequence + 1); - ::basegfx::B2DVector aVec1(aPrev.X - aCurr.X, aPrev.Y - aCurr.Y); - ::basegfx::B2DVector aVec2(aNext.X - aCurr.X, aNext.Y - aCurr.Y); - bool bSameLength(false); - bool bSameDirection(false); - - // get vector values - Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection); - - // set correct flag value - if(bSameDirection) - { - if(bSameLength) - { - // set to PolygonFlags_SYMMETRIC - *pInnerFlags = drawing::PolygonFlags_SYMMETRIC; - *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SYMMETRIC; - } - else - { - // set to PolygonFlags_SMOOTH - *pInnerFlags = drawing::PolygonFlags_SMOOTH; - *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SMOOTH; - } - } - else - { - // set to PolygonFlags_NORMAL - *pInnerFlags = drawing::PolygonFlags_NORMAL; - *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_NORMAL; - } - } - } - - // switch to next Polygon - pOuterSequence++; - pOuterFlags++; - } - } - } + // object size and ViewBox size different? + basegfx::B2DHomMatrix aTransform; + const bool bScale(rObjectSize.Width != mrViewBox.GetWidth() + || rObjectSize.Height != mrViewBox.GetHeight()); + const bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L); + + if( bTranslate ) + aTransform.translate( + -mrViewBox.GetX(), + -mrViewBox.GetY()); + if( bScale ) + aTransform.scale( + rObjectSize.Width / mrViewBox.GetWidth(), + rObjectSize.Height / mrViewBox.GetHeight()); + aTransform.translate( rObjectPos.X, rObjectPos.Y ); + aPoly.transform(aTransform); + + basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier(aPoly,maPoly); } // eof |