summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <alg@apache.org>2013-10-29 14:11:45 +0000
committerCaolán McNamara <caolanm@redhat.com>2013-10-31 15:56:14 +0000
commit223f6b631c1b087754c0f9051fb55f029f2503ce (patch)
tree14582be2894a88d16c6b0debbc8491350f9a5cce
parent9069e26d1fe1fbbe7bceab0bae8a186d8cdb47cc (diff)
Resolves: #i123433# Detect pseudo-vertices at svg import...
unify svg:d handling, correct svg:d import for relative sub-polygons in svg import; changed default for moveto writes for svg:d in ODF to absolute (cherry picked from commit f15874d8f976f3874bdbcb53429eeefa65c28841) Conflicts: basegfx/inc/basegfx/polygon/b2dpolygontools.hxx basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx basegfx/inc/basegfx/polygon/b3dpolypolygontools.hxx basegfx/source/polygon/b2dpolypolygontools.cxx basegfx/source/polygon/b2dsvgpolypolygon.cxx basegfx/source/polygon/b3dpolypolygontools.cxx basegfx/source/tools/makefile.mk basegfx/test/boxclipper.cxx basegfx/test/clipstate.cxx basegfx/test/genericclipper.cxx canvas/source/tools/surfaceproxy.cxx sdext/source/pdfimport/tree/drawtreevisiting.cxx sdext/source/pdfimport/tree/writertreevisiting.cxx xmloff/inc/xexptran.hxx xmloff/source/draw/XMLImageMapContext.cxx xmloff/source/draw/XMLImageMapExport.cxx xmloff/source/draw/shapeexport2.cxx xmloff/source/draw/shapeexport3.cxx xmloff/source/draw/xexptran.cxx xmloff/source/draw/ximp3dobject.cxx xmloff/source/draw/ximpshap.cxx xmloff/source/style/MarkerStyle.cxx xmloff/source/text/XMLTextFrameContext.cxx xmloff/source/text/txtparae.cxx Change-Id: I5171b4a3559ea116bea45152e1f2685666463635
-rw-r--r--basebmp/CppunitTest_basebmp.mk2
-rw-r--r--basebmp/test/bmpmasktest.cxx4
-rw-r--r--basebmp/test/bmptest.cxx2
-rw-r--r--basebmp/test/cliptest.cxx4
-rw-r--r--basebmp/test/filltest.cxx2
-rw-r--r--basebmp/test/masktest.cxx2
-rw-r--r--basebmp/test/polytest.cxx22
-rw-r--r--basegfx/Library_basegfx.mk1
-rw-r--r--basegfx/source/inc/stringconversiontools.hxx96
-rw-r--r--basegfx/source/polygon/b2dpolygontools.cxx343
-rw-r--r--basegfx/source/polygon/b2dpolypolygontools.cxx114
-rw-r--r--basegfx/source/polygon/b2dsvgpolypolygon.cxx474
-rw-r--r--basegfx/source/polygon/b3dpolypolygontools.cxx153
-rw-r--r--basegfx/source/tools/stringconversiontools.cxx169
-rw-r--r--basegfx/test/basegfx2d.cxx40
-rw-r--r--basegfx/test/boxclipper.cxx21
-rw-r--r--basegfx/test/clipstate.cxx13
-rw-r--r--basegfx/test/genericclipper.cxx14
-rw-r--r--canvas/source/tools/surfaceproxy.cxx4
-rw-r--r--filter/source/svg/svgreader.cxx7
-rw-r--r--include/basegfx/polygon/b2dpolygontools.hxx54
-rw-r--r--include/basegfx/polygon/b2dpolypolygontools.hxx103
-rw-r--r--include/basegfx/polygon/b3dpolypolygontools.hxx11
-rw-r--r--sd/source/core/CustomAnimationEffect.cxx4
-rw-r--r--sdext/source/pdfimport/test/tests.cxx6
-rw-r--r--sdext/source/pdfimport/tree/drawtreevisiting.cxx2
-rw-r--r--sdext/source/pdfimport/tree/writertreevisiting.cxx2
-rw-r--r--slideshow/source/engine/animationfactory.cxx2
-rw-r--r--svgio/inc/svgio/svgreader/svgpathnode.hxx10
-rw-r--r--svgio/inc/svgio/svgreader/svgstyleattributes.hxx7
-rw-r--r--svgio/source/svgreader/svgcirclenode.cxx2
-rw-r--r--svgio/source/svgreader/svgellipsenode.cxx2
-rw-r--r--svgio/source/svgreader/svglinenode.cxx2
-rw-r--r--svgio/source/svgreader/svgpathnode.cxx4
-rw-r--r--svgio/source/svgreader/svgpolynode.cxx3
-rw-r--r--svgio/source/svgreader/svgrectnode.cxx2
-rw-r--r--svgio/source/svgreader/svgstyleattributes.cxx20
-rw-r--r--xmloff/inc/xexptran.hxx78
-rw-r--r--xmloff/source/draw/XMLImageMapContext.cxx35
-rw-r--r--xmloff/source/draw/XMLImageMapExport.cxx63
-rw-r--r--xmloff/source/draw/shapeexport.cxx302
-rw-r--r--xmloff/source/draw/xexptran.cxx909
-rw-r--r--xmloff/source/draw/ximp3dobject.cxx74
-rw-r--r--xmloff/source/draw/ximpshap.cxx247
-rw-r--r--xmloff/source/style/MarkerStyle.cxx151
-rw-r--r--xmloff/source/text/XMLTextFrameContext.cxx62
-rw-r--r--xmloff/source/text/txtparae.cxx118
47 files changed, 1799 insertions, 1963 deletions
diff --git a/basebmp/CppunitTest_basebmp.mk b/basebmp/CppunitTest_basebmp.mk
index 67113ff0d874..c2ffb5f7d5b6 100644
--- a/basebmp/CppunitTest_basebmp.mk
+++ b/basebmp/CppunitTest_basebmp.mk
@@ -9,6 +9,8 @@
$(eval $(call gb_CppunitTest_CppunitTest,basebmp_cpputest))
+$(eval $(call gb_CppunitTest_use_sdk_api,basebmp_cpputest))
+
$(eval $(call gb_CppunitTest_use_external,basebmp_cpputest,boost_headers))
$(eval $(call gb_CppunitTest_use_libraries,basebmp_cpputest,\
diff --git a/basebmp/test/bmpmasktest.cxx b/basebmp/test/bmpmasktest.cxx
index d98fb6209606..a0209dfabfd6 100644
--- a/basebmp/test/bmpmasktest.cxx
+++ b/basebmp/test/bmpmasktest.cxx
@@ -112,7 +112,7 @@ public:
OUString aSvg( "m 0 0h5v10h5v-5h-10z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
const Color aColWhite(0xFFFFFFFF);
const Color aColBlack(0);
mpBmp1bpp->fillPolyPolygon(
@@ -127,7 +127,7 @@ public:
aSvg = "m 0 0 h6 v10 h-6z" ;
aPoly.clear();
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
mpMaskBmp1bpp->clear(aColWhite);
mpMaskBmp1bpp->fillPolyPolygon(
aPoly,
diff --git a/basebmp/test/bmptest.cxx b/basebmp/test/bmptest.cxx
index 59adac5feeae..e364804a391e 100644
--- a/basebmp/test/bmptest.cxx
+++ b/basebmp/test/bmptest.cxx
@@ -165,7 +165,7 @@ public:
OUString aSvg( "m 0 0h5v10h5v-5h-10z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
const Color aCol(0xFFFFFFFF);
mpBmp1bpp->fillPolyPolygon(
aPoly,
diff --git a/basebmp/test/cliptest.cxx b/basebmp/test/cliptest.cxx
index cc1dbb0ce384..bcde756adeee 100644
--- a/basebmp/test/cliptest.cxx
+++ b/basebmp/test/cliptest.cxx
@@ -161,7 +161,7 @@ private:
OUString aSvg( "m 0 0h5v10h5v-5h-10z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
const basebmp::Color aCol(0xFF);
pBmp->clear( basebmp::Color(0) );
pBmp->fillPolyPolygon(
@@ -200,7 +200,7 @@ public:
OUString aSvg( "m 0 0 h5 l5 5 v5 h-5 l-5-5 z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
mpClipMask->clear(Color(0));
mpClipMask->drawPolygon(
aPoly.getB2DPolygon(0),
diff --git a/basebmp/test/filltest.cxx b/basebmp/test/filltest.cxx
index 6c0079583cd5..3adf26a0a97c 100644
--- a/basebmp/test/filltest.cxx
+++ b/basebmp/test/filltest.cxx
@@ -149,7 +149,7 @@ private:
OUString aSvg( "m 0 0l7 7h-1z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
diff --git a/basebmp/test/masktest.cxx b/basebmp/test/masktest.cxx
index bdc870d28193..1662c81f9b98 100644
--- a/basebmp/test/masktest.cxx
+++ b/basebmp/test/masktest.cxx
@@ -116,7 +116,7 @@ public:
OUString aSvg( "m 0 0h5v10h5v-5h-10z" );
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD( aPoly, aSvg );
+ basegfx::tools::importFromSvgD( aPoly, aSvg, false, NULL );
const Color aCol(0xFF);
mpMask->fillPolyPolygon(
aPoly,
diff --git a/basebmp/test/polytest.cxx b/basebmp/test/polytest.cxx
index a32d099c3834..3ed416b1dfef 100644
--- a/basebmp/test/polytest.cxx
+++ b/basebmp/test/polytest.cxx
@@ -54,7 +54,7 @@ private:
basegfx::tools::importFromSvgD(
aPoly,
- OUString( "M2 2 l7 7 z" ) );
+ OUString( "M2 2 l7 7 z" ), false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
@@ -68,7 +68,7 @@ private:
aPoly.clear();
basegfx::tools::importFromSvgD(
aPoly,
- OUString( "M7 2 l-6 6 z" ) );
+ OUString( "M7 2 l-6 6 z" ), false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
@@ -86,7 +86,7 @@ private:
basegfx::tools::importFromSvgD(
aPoly,
- OUString( "M2 2 h1 l7 7 h-1 z" ) );
+ OUString( "M2 2 h1 l7 7 h-1 z" ), false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
@@ -100,7 +100,7 @@ private:
aPoly.clear();
basegfx::tools::importFromSvgD(
aPoly,
- OUString( "M7 2 h-1 l-6 6 h1 z" ) );
+ OUString( "M7 2 h-1 l-6 6 h1 z" ), false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
@@ -114,7 +114,7 @@ private:
aPoly.clear();
basegfx::tools::importFromSvgD(
aPoly,
- OUString( "M0 0 l7 7 h-1 l-5-7 z" ) );
+ OUString( "M0 0 l7 7 h-1 l-5-7 z" ), false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
@@ -131,7 +131,8 @@ private:
basegfx::B2DPolyPolygon aPoly;
basegfx::tools::importFromSvgD( aPoly,
- OUString( "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" ) );
+ OUString( "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" ),
+ false, NULL );
rDevice->fillPolyPolygon(
aPoly,
@@ -149,7 +150,8 @@ private:
basegfx::B2DPolyPolygon aPoly;
basegfx::tools::importFromSvgD( aPoly,
- OUString( "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" ) );
+ OUString( "M0 0 h7 v7 h-7 z M2 2 v3 h3 v-3 z" ),
+ false, NULL );
basegfx::B2DHomMatrix aMat;
aMat.translate(-3,-3);
aMat.rotate( 1.7 );
@@ -249,7 +251,8 @@ private:
// *all* of the four two-pixel lines in that polygon do *not*
// generate a single pixel, due to the rasterization effect.
basegfx::tools::importFromSvgD( aPoly,
- OUString( "M2 3 l1 -1 M4 2 l1 1 M2 8 l1 1 M5 8 l-1 1 M2 5 h4 M3 0 v10" ) );
+ OUString( "M2 3 l1 -1 M4 2 l1 1 M2 8 l1 1 M5 8 l-1 1 M2 5 h4 M3 0 v10" ),
+ false, NULL );
BitmapDeviceSharedPtr pClippedDevice=(
subsetBitmapDevice( rDevice,
basegfx::B2IBox(3,3,5,9) ));
@@ -276,7 +279,8 @@ private:
"M10 6 v-2 l-10 2 v2 z"
"M1 0 h1 v10 h-1 z"
"M4 0 h1 v10 h-1 z"
- "M8 0 h1 v10 h-1 z" ) );
+ "M8 0 h1 v10 h-1 z" ),
+ false, NULL );
rDevice->fillPolyPolygon(
aPoly,
aCol,
diff --git a/basegfx/Library_basegfx.mk b/basegfx/Library_basegfx.mk
index 5956d6ee18e2..f121f69cae78 100644
--- a/basegfx/Library_basegfx.mk
+++ b/basegfx/Library_basegfx.mk
@@ -70,6 +70,7 @@ $(eval $(call gb_Library_add_exception_objects,basegfx,\
basegfx/source/tools/gradienttools \
basegfx/source/tools/keystoplerp \
basegfx/source/tools/numbertools \
+ basegfx/source/tools/stringconversiontools \
basegfx/source/tools/tools \
basegfx/source/tools/unopolypolygon \
basegfx/source/tools/unotools \
diff --git a/basegfx/source/inc/stringconversiontools.hxx b/basegfx/source/inc/stringconversiontools.hxx
new file mode 100644
index 000000000000..96692dcf2bb4
--- /dev/null
+++ b/basegfx/source/inc/stringconversiontools.hxx
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef _STRINGCONVERSIONTOOLS_HXX
+#define _STRINGCONVERSIONTOOLS_HXX
+
+#include <sal/types.h>
+#include <rtl/ustring.hxx>
+#include <rtl/ustrbuf.hxx>
+
+namespace basegfx
+{
+ namespace internal
+ {
+ void lcl_skipSpaces(sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen);
+
+ void lcl_skipSpacesAndCommas(sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen);
+
+ inline bool lcl_isOnNumberChar(const sal_Unicode aChar, bool bSignAllowed = true)
+ {
+ const bool bPredicate( (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
+ || (bSignAllowed && sal_Unicode('+') == aChar)
+ || (bSignAllowed && sal_Unicode('-') == aChar) );
+
+ return bPredicate;
+ }
+
+ inline bool lcl_isOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
+ {
+ return lcl_isOnNumberChar(rStr[nPos],
+ bSignAllowed);
+ }
+
+ bool lcl_getDoubleChar(double& o_fRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr);
+
+ bool lcl_importDoubleAndSpaces( double& o_fRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen );
+
+ bool lcl_importFlagAndSpaces(sal_Int32& o_nRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen);
+
+ void lcl_skipNumber(sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen);
+
+ void lcl_skipDouble(sal_Int32& io_rPos,
+ const OUString& rStr);
+
+ inline void lcl_putNumberChar( OUStringBuffer& rStr,
+ double fValue )
+ {
+ rStr.append( fValue );
+ }
+
+ void lcl_putNumberCharWithSpace( OUStringBuffer& rStr,
+ double fValue,
+ double fOldValue,
+ bool bUseRelativeCoordinates );
+
+ inline sal_Unicode lcl_getCommand( sal_Char cUpperCaseCommand,
+ sal_Char cLowerCaseCommand,
+ bool bUseRelativeCoordinates )
+ {
+ return bUseRelativeCoordinates ? cLowerCaseCommand : cUpperCaseCommand;
+ }
+ } // namespace internal
+} // namespace basegfx
+
+#endif /* _STRINGCONVERSIONTOOLS_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/polygon/b2dpolygontools.cxx b/basegfx/source/polygon/b2dpolygontools.cxx
index f9fec004e15c..535e8cd6acda 100644
--- a/basegfx/source/polygon/b2dpolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolygontools.cxx
@@ -3352,6 +3352,349 @@ namespace basegfx
return aRetval;
}
+ //////////////////////////////////////////////////////////////////////////////
+ // converters for com::sun::star::drawing::PointSequence
+
+ B2DPolygon UnoPointSequenceToB2DPolygon(
+ const com::sun::star::drawing::PointSequence& rPointSequenceSource,
+ bool bCheckClosed)
+ {
+ B2DPolygon aRetval;
+ const sal_uInt32 nLength(rPointSequenceSource.getLength());
+
+ if(nLength)
+ {
+ aRetval.reserve(nLength);
+ const com::sun::star::awt::Point* pArray = rPointSequenceSource.getConstArray();
+ const com::sun::star::awt::Point* pArrayEnd = pArray + rPointSequenceSource.getLength();
+
+ for(;pArray != pArrayEnd; pArray++)
+ {
+ aRetval.append(B2DPoint(pArray->X, pArray->Y));
+ }
+
+ if(bCheckClosed)
+ {
+ // check for closed state flag
+ tools::checkClosed(aRetval);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void B2DPolygonToUnoPointSequence(
+ const B2DPolygon& rPolygon,
+ com::sun::star::drawing::PointSequence& rPointSequenceRetval)
+ {
+ B2DPolygon aPolygon(rPolygon);
+
+ if(aPolygon.areControlPointsUsed())
+ {
+ OSL_ENSURE(false, "B2DPolygonToUnoPointSequence: Source contains bezier segments, wrong UNO API data type may be used (!)");
+ aPolygon = aPolygon.getDefaultAdaptiveSubdivision();
+ }
+
+ const sal_uInt32 nPointCount(aPolygon.count());
+
+ if(nPointCount)
+ {
+ // Take closed state into account, the API polygon still uses the old closed definition
+ // with last/first point are identical (cannot hold information about open polygons with identical
+ // first and last point, though)
+ const bool bIsClosed(aPolygon.isClosed());
+
+ rPointSequenceRetval.realloc(bIsClosed ? nPointCount + 1 : nPointCount);
+ com::sun::star::awt::Point* pSequence = rPointSequenceRetval.getArray();
+
+ for(sal_uInt32 b(0); b < nPointCount; b++)
+ {
+ const B2DPoint aPoint(aPolygon.getB2DPoint(b));
+ const com::sun::star::awt::Point aAPIPoint(fround(aPoint.getX()), fround(aPoint.getY()));
+
+ *pSequence = aAPIPoint;
+ pSequence++;
+ }
+
+ // copy first point if closed
+ if(bIsClosed)
+ {
+ *pSequence = *rPointSequenceRetval.getArray();
+ }
+ }
+ else
+ {
+ rPointSequenceRetval.realloc(0);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // converters for com::sun::star::drawing::PointSequence and
+ // com::sun::star::drawing::FlagSequence to B2DPolygon (curved polygons)
+
+ B2DPolygon UnoPolygonBezierCoordsToB2DPolygon(
+ const com::sun::star::drawing::PointSequence& rPointSequenceSource,
+ const com::sun::star::drawing::FlagSequence& rFlagSequenceSource,
+ bool bCheckClosed)
+ {
+ const sal_uInt32 nCount((sal_uInt32)rPointSequenceSource.getLength());
+ OSL_ENSURE(nCount == (sal_uInt32)rFlagSequenceSource.getLength(),
+ "UnoPolygonBezierCoordsToB2DPolygon: Unequal count of Points and Flags (!)");
+
+ // prepare new polygon
+ B2DPolygon aRetval;
+ const com::sun::star::awt::Point* pPointSequence = rPointSequenceSource.getConstArray();
+ const com::sun::star::drawing::PolygonFlags* pFlagSequence = rFlagSequenceSource.getConstArray();
+
+ // get first point and flag
+ B2DPoint aNewCoordinatePair(pPointSequence->X, pPointSequence->Y); pPointSequence++;
+ com::sun::star::drawing::PolygonFlags ePolygonFlag(*pFlagSequence); pFlagSequence++;
+ B2DPoint aControlA;
+ B2DPoint aControlB;
+
+ // first point is not allowed to be a control point
+ OSL_ENSURE(com::sun::star::drawing::PolygonFlags_CONTROL != ePolygonFlag,
+ "UnoPolygonBezierCoordsToB2DPolygon: Start point is a control point, illegal input polygon (!)");
+
+ // add first point as start point
+ aRetval.append(aNewCoordinatePair);
+
+ for(sal_uInt32 b(1); b < nCount;)
+ {
+ // prepare loop
+ bool bControlA(false);
+ bool bControlB(false);
+
+ // get next point and flag
+ aNewCoordinatePair = B2DPoint(pPointSequence->X, pPointSequence->Y);
+ ePolygonFlag = *pFlagSequence;
+ pPointSequence++; pFlagSequence++; b++;
+
+ if(b < nCount && com::sun::star::drawing::PolygonFlags_CONTROL == ePolygonFlag)
+ {
+ aControlA = aNewCoordinatePair;
+ bControlA = true;
+
+ // get next point and flag
+ aNewCoordinatePair = B2DPoint(pPointSequence->X, pPointSequence->Y);
+ ePolygonFlag = *pFlagSequence;
+ pPointSequence++; pFlagSequence++; b++;
+ }
+
+ if(b < nCount && com::sun::star::drawing::PolygonFlags_CONTROL == ePolygonFlag)
+ {
+ aControlB = aNewCoordinatePair;
+ bControlB = true;
+
+ // get next point and flag
+ aNewCoordinatePair = B2DPoint(pPointSequence->X, pPointSequence->Y);
+ ePolygonFlag = *pFlagSequence;
+ pPointSequence++; pFlagSequence++; b++;
+ }
+
+ // two or no control points are consumed, another one would be an error.
+ // It's also an error if only one control point was read
+ OSL_ENSURE(com::sun::star::drawing::PolygonFlags_CONTROL != ePolygonFlag && bControlA == bControlB,
+ "UnoPolygonBezierCoordsToB2DPolygon: Illegal source polygon (!)");
+
+ // the previous writes used the B2DPolyPoygon -> PolyPolygon converter
+ // which did not create minimal PolyPolygons, but created all control points
+ // as null vectors (identical points). Because of the former P(CA)(CB)-norm of
+ // B2DPolygon and it's unused sign of being the zero-vector and CA and CB being
+ // relative to P, an empty edge was exported as P == CA == CB. Luckily, the new
+ // export format can be read without errors by the old OOo-versions, so we need only
+ // to correct here at read and do not need to export a wrong but compatible version
+ // for the future.
+ if(bControlA
+ && aControlA.equal(aControlB)
+ && aControlA.equal(aRetval.getB2DPoint(aRetval.count() - 1)))
+ {
+ bControlA = bControlB = false;
+ }
+
+ if(bControlA)
+ {
+ // add bezier edge
+ aRetval.appendBezierSegment(aControlA, aControlB, aNewCoordinatePair);
+ }
+ else
+ {
+ // add edge
+ aRetval.append(aNewCoordinatePair);
+ }
+ }
+
+ // #i72807# API import uses old line start/end-equal definition for closed,
+ // so we need to correct this to closed state here
+ if(bCheckClosed)
+ {
+ checkClosed(aRetval);
+ }
+
+ return aRetval;
+ }
+
+ void B2DPolygonToUnoPolygonBezierCoords(
+ const B2DPolygon& rPolygon,
+ com::sun::star::drawing::PointSequence& rPointSequenceRetval,
+ com::sun::star::drawing::FlagSequence& rFlagSequenceRetval)
+ {
+ const sal_uInt32 nPointCount(rPolygon.count());
+
+ if(nPointCount)
+ {
+ const bool bCurve(rPolygon.areControlPointsUsed());
+ const bool bClosed(rPolygon.isClosed());
+
+ if(nPointCount)
+ {
+ if(bCurve)
+ {
+ // calculate target point count
+ const sal_uInt32 nLoopCount(bClosed ? nPointCount : (nPointCount ? nPointCount - 1 : 0));
+
+ if(nLoopCount)
+ {
+ // prepare target data. The real needed number of target points (and flags)
+ // could only be calculated by using two loops, so use dynamic memory
+ std::vector< com::sun::star::awt::Point > aCollectPoints;
+ std::vector< com::sun::star::drawing::PolygonFlags > aCollectFlags;
+
+ // reserve maximum creatable points
+ const sal_uInt32 nMaxTargetCount((nLoopCount * 3) + 1);
+ aCollectPoints.reserve(nMaxTargetCount);
+ aCollectFlags.reserve(nMaxTargetCount);
+
+ // prepare current bezier segment by setting start point
+ B2DCubicBezier aBezierSegment;
+ aBezierSegment.setStartPoint(rPolygon.getB2DPoint(0));
+
+ for(sal_uInt32 a(0); a < nLoopCount; a++)
+ {
+ // add current point (always) and remember StartPointIndex for evtl. later corrections
+ const sal_uInt32 nStartPointIndex(aCollectPoints.size());
+ aCollectPoints.push_back(
+ com::sun::star::awt::Point(
+ fround(aBezierSegment.getStartPoint().getX()),
+ fround(aBezierSegment.getStartPoint().getY())));
+ aCollectFlags.push_back(com::sun::star::drawing::PolygonFlags_NORMAL);
+
+ // prepare next segment
+ const sal_uInt32 nNextIndex((a + 1) % nPointCount);
+ aBezierSegment.setEndPoint(rPolygon.getB2DPoint(nNextIndex));
+ aBezierSegment.setControlPointA(rPolygon.getNextControlPoint(a));
+ aBezierSegment.setControlPointB(rPolygon.getPrevControlPoint(nNextIndex));
+
+ if(aBezierSegment.isBezier())
+ {
+ // if bezier is used, add always two control points due to the old schema
+ aCollectPoints.push_back(
+ com::sun::star::awt::Point(
+ fround(aBezierSegment.getControlPointA().getX()),
+ fround(aBezierSegment.getControlPointA().getY())));
+ aCollectFlags.push_back(com::sun::star::drawing::PolygonFlags_CONTROL);
+
+ aCollectPoints.push_back(
+ com::sun::star::awt::Point(
+ fround(aBezierSegment.getControlPointB().getX()),
+ fround(aBezierSegment.getControlPointB().getY())));
+ aCollectFlags.push_back(com::sun::star::drawing::PolygonFlags_CONTROL);
+ }
+
+ // test continuity with previous control point to set flag value
+ if(aBezierSegment.getControlPointA() != aBezierSegment.getStartPoint() && (bClosed || a))
+ {
+ const B2VectorContinuity eCont(rPolygon.getContinuityInPoint(a));
+
+ if(CONTINUITY_C1 == eCont)
+ {
+ aCollectFlags[nStartPointIndex] = com::sun::star::drawing::PolygonFlags_SMOOTH;
+ }
+ else if(CONTINUITY_C2 == eCont)
+ {
+ aCollectFlags[nStartPointIndex] = com::sun::star::drawing::PolygonFlags_SYMMETRIC;
+ }
+ }
+
+ // prepare next loop
+ aBezierSegment.setStartPoint(aBezierSegment.getEndPoint());
+ }
+
+ if(bClosed)
+ {
+ // add first point again as closing point due to old definition
+ aCollectPoints.push_back(aCollectPoints[0]);
+ aCollectFlags.push_back(com::sun::star::drawing::PolygonFlags_NORMAL);
+ }
+ else
+ {
+ // add last point as closing point
+ const B2DPoint aClosingPoint(rPolygon.getB2DPoint(nPointCount - 1L));
+ aCollectPoints.push_back(
+ com::sun::star::awt::Point(
+ fround(aClosingPoint.getX()),
+ fround(aClosingPoint.getY())));
+ aCollectFlags.push_back(com::sun::star::drawing::PolygonFlags_NORMAL);
+ }
+
+ // copy collected data to target arrays
+ const sal_uInt32 nTargetCount(aCollectPoints.size());
+ OSL_ENSURE(nTargetCount == aCollectFlags.size(), "Unequal Point and Flag count (!)");
+
+ rPointSequenceRetval.realloc((sal_Int32)nTargetCount);
+ rFlagSequenceRetval.realloc((sal_Int32)nTargetCount);
+ com::sun::star::awt::Point* pPointSequence = rPointSequenceRetval.getArray();
+ com::sun::star::drawing::PolygonFlags* pFlagSequence = rFlagSequenceRetval.getArray();
+
+ for(sal_uInt32 a(0); a < nTargetCount; a++)
+ {
+ *pPointSequence = aCollectPoints[a];
+ *pFlagSequence = aCollectFlags[a];
+ pPointSequence++;
+ pFlagSequence++;
+ }
+ }
+ }
+ else
+ {
+ // straightforward point list creation
+ const sal_uInt32 nTargetCount(nPointCount + (bClosed ? 1 : 0));
+
+ rPointSequenceRetval.realloc((sal_Int32)nTargetCount);
+ rFlagSequenceRetval.realloc((sal_Int32)nTargetCount);
+
+ com::sun::star::awt::Point* pPointSequence = rPointSequenceRetval.getArray();
+ com::sun::star::drawing::PolygonFlags* pFlagSequence = rFlagSequenceRetval.getArray();
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const B2DPoint aB2DPoint(rPolygon.getB2DPoint(a));
+ const com::sun::star::awt::Point aAPIPoint(
+ fround(aB2DPoint.getX()),
+ fround(aB2DPoint.getY()));
+
+ *pPointSequence = aAPIPoint;
+ *pFlagSequence = com::sun::star::drawing::PolygonFlags_NORMAL;
+ pPointSequence++;
+ pFlagSequence++;
+ }
+
+ if(bClosed)
+ {
+ // add first point as closing point
+ *pPointSequence = *rPointSequenceRetval.getConstArray();
+ *pFlagSequence = com::sun::star::drawing::PolygonFlags_NORMAL;
+ }
+ }
+ }
+ }
+ else
+ {
+ rPointSequenceRetval.realloc(0);
+ rFlagSequenceRetval.realloc(0);
+ }
+ }
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/basegfx/source/polygon/b2dpolypolygontools.cxx b/basegfx/source/polygon/b2dpolypolygontools.cxx
index 11a3e8a29615..f1ba12b67663 100644
--- a/basegfx/source/polygon/b2dpolypolygontools.cxx
+++ b/basegfx/source/polygon/b2dpolypolygontools.cxx
@@ -24,7 +24,6 @@
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
-
#include <numeric>
//////////////////////////////////////////////////////////////////////////////
@@ -648,6 +647,119 @@ namespace basegfx
return aRes;
}
+ //////////////////////////////////////////////////////////////////////////////
+ // converters for com::sun::star::drawing::PointSequence
+
+ B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
+ const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
+ bool bCheckClosed)
+ {
+ B2DPolyPolygon aRetval;
+ const com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceSource.getConstArray();
+ const com::sun::star::drawing::PointSequence* pPointSeqEnd = pPointSequence + rPointSequenceSequenceSource.getLength();
+
+ for(;pPointSequence != pPointSeqEnd; pPointSequence++)
+ {
+ const B2DPolygon aNewPolygon = UnoPointSequenceToB2DPolygon(*pPointSequence, bCheckClosed);
+ aRetval.append(aNewPolygon);
+ }
+
+ return aRetval;
+ }
+
+ void B2DPolyPolygonToUnoPointSequenceSequence(
+ const B2DPolyPolygon& rPolyPolygon,
+ com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval)
+ {
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if(nCount)
+ {
+ rPointSequenceSequenceRetval.realloc(nCount);
+ com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceRetval.getArray();
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(a));
+
+ B2DPolygonToUnoPointSequence(aPolygon, *pPointSequence);
+ pPointSequence++;
+ }
+ }
+ else
+ {
+ rPointSequenceSequenceRetval.realloc(0);
+ }
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
+
+ B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
+ const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
+ bool bCheckClosed)
+ {
+ B2DPolyPolygon aRetval;
+ const sal_uInt32 nSequenceCount((sal_uInt32)rPolyPolygonBezierCoordsSource.Coordinates.getLength());
+
+ if(nSequenceCount)
+ {
+ OSL_ENSURE(nSequenceCount == (sal_uInt32)rPolyPolygonBezierCoordsSource.Flags.getLength(),
+ "UnoPolyPolygonBezierCoordsToB2DPolyPolygon: unequal number of Points and Flags (!)");
+ const com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsSource.Coordinates.getConstArray();
+ const com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsSource.Flags.getConstArray();
+
+ for(sal_uInt32 a(0); a < nSequenceCount; a++)
+ {
+ const B2DPolygon aNewPolygon(UnoPolygonBezierCoordsToB2DPolygon(
+ *pPointSequence,
+ *pFlagSequence,
+ bCheckClosed));
+
+ pPointSequence++;
+ pFlagSequence++;
+ aRetval.append(aNewPolygon);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ const B2DPolyPolygon& rPolyPolygon,
+ com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval)
+ {
+ const sal_uInt32 nCount(rPolyPolygon.count());
+
+ if(nCount)
+ {
+ // prepare return value memory
+ rPolyPolygonBezierCoordsRetval.Coordinates.realloc((sal_Int32)nCount);
+ rPolyPolygonBezierCoordsRetval.Flags.realloc((sal_Int32)nCount);
+
+ // get pointers to arrays
+ com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsRetval.Coordinates.getArray();
+ com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsRetval.Flags.getArray();
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const B2DPolygon aSource(rPolyPolygon.getB2DPolygon(a));
+
+ B2DPolygonToUnoPolygonBezierCoords(
+ aSource,
+ *pPointSequence,
+ *pFlagSequence);
+ pPointSequence++;
+ pFlagSequence++;
+ }
+ }
+ else
+ {
+ rPolyPolygonBezierCoordsRetval.Coordinates.realloc(0);
+ rPolyPolygonBezierCoordsRetval.Flags.realloc(0);
+ }
+ }
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/basegfx/source/polygon/b2dsvgpolypolygon.cxx b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
index 6a1dffa4e3a5..46675643ae81 100644
--- a/basegfx/source/polygon/b2dsvgpolypolygon.cxx
+++ b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
@@ -24,227 +24,91 @@
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <rtl/ustring.hxx>
#include <rtl/math.hxx>
+#include <stringconversiontools.hxx>
namespace basegfx
{
namespace tools
{
- namespace
+ bool PointIndex::operator<(const PointIndex& rComp) const
{
- void lcl_skipSpaces(sal_Int32& io_rPos,
- const OUString& rStr,
- const sal_Int32 nLen)
+ if(rComp.getPolygonIndex() == getPolygonIndex())
{
- while( io_rPos < nLen &&
- sal_Unicode(' ') == rStr[io_rPos] )
- {
- ++io_rPos;
- }
- }
-
- void lcl_skipSpacesAndCommas(sal_Int32& io_rPos,
- const OUString& rStr,
- const sal_Int32 nLen)
- {
- while(io_rPos < nLen
- && (sal_Unicode(' ') == rStr[io_rPos] || sal_Unicode(',') == rStr[io_rPos]))
- {
- ++io_rPos;
- }
- }
-
- inline bool lcl_isOnNumberChar(const sal_Unicode aChar, bool bSignAllowed = true)
- {
- const bool bPredicate( (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
- || (bSignAllowed && sal_Unicode('+') == aChar)
- || (bSignAllowed && sal_Unicode('-') == aChar)
- || (sal_Unicode('.') == aChar) );
-
- return bPredicate;
- }
-
- inline bool lcl_isOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
- {
- return lcl_isOnNumberChar(rStr[nPos],
- bSignAllowed);
- }
-
- bool lcl_getDoubleChar(double& o_fRetval,
- sal_Int32& io_rPos,
- const OUString& rStr)
- {
- sal_Unicode aChar( rStr[io_rPos] );
- OUStringBuffer sNumberString;
- bool separator_seen=false;
-
- if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
- {
- sNumberString.append(rStr[io_rPos]);
- aChar = rStr[++io_rPos];
- }
-
- while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
- || (!separator_seen && sal_Unicode('.') == aChar))
- {
- if (sal_Unicode('.') == aChar) separator_seen = true;
- sNumberString.append(rStr[io_rPos]);
- io_rPos++;
- aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
- }
-
- if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
- {
- sNumberString.append(rStr[io_rPos]);
- io_rPos++;
- aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
-
- if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
- {
- sNumberString.append(rStr[io_rPos]);
- io_rPos++;
- aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
- }
-
- while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
- {
- sNumberString.append(rStr[io_rPos]);
- io_rPos++;
- aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
- }
- }
-
- if(!sNumberString.isEmpty())
- {
- rtl_math_ConversionStatus eStatus;
- o_fRetval = ::rtl::math::stringToDouble( sNumberString.makeStringAndClear(),
- (sal_Unicode)('.'),
- (sal_Unicode)(','),
- &eStatus,
- NULL );
- return ( eStatus == rtl_math_ConversionStatus_Ok );
- }
-
- return false;
- }
-
- bool lcl_importDoubleAndSpaces( double& o_fRetval,
- sal_Int32& io_rPos,
- const OUString& rStr,
- const sal_Int32 nLen )
- {
- if( !lcl_getDoubleChar(o_fRetval, io_rPos, rStr) )
- return false;
-
- lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
-
- return true;
- }
-
- bool lcl_importFlagAndSpaces(sal_Int32& o_nRetval,
- sal_Int32& io_rPos,
- const OUString& rStr,
- const sal_Int32 nLen)
- {
- sal_Unicode aChar( rStr[io_rPos] );
-
- if(sal_Unicode('0') == aChar)
- {
- o_nRetval = 0;
- ++io_rPos;
- }
- else if (sal_Unicode('1') == aChar)
- {
- o_nRetval = 1;
- ++io_rPos;
- }
- else
- return false;
-
- lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
-
- return true;
- }
-
- void lcl_putNumberChar( OUStringBuffer& rStr,
- double fValue )
- {
- rStr.append( fValue );
- }
-
- void lcl_putNumberCharWithSpace( OUStringBuffer& rStr,
- double fValue,
- double fOldValue,
- bool bUseRelativeCoordinates )
- {
- if( bUseRelativeCoordinates )
- fValue -= fOldValue;
-
- const sal_Int32 aLen( rStr.getLength() );
- if(aLen > 0)
- {
- if( lcl_isOnNumberChar(rStr[aLen - 1], false) &&
- fValue >= 0.0 )
- {
- rStr.append( sal_Unicode(' ') );
- }
- }
-
- lcl_putNumberChar(rStr, fValue);
+ return rComp.getPointIndex() < getPointIndex();
}
- inline sal_Unicode lcl_getCommand( sal_Char cUpperCaseCommand,
- sal_Char cLowerCaseCommand,
- bool bUseRelativeCoordinates )
- {
- return bUseRelativeCoordinates ? cLowerCaseCommand : cUpperCaseCommand;
- }
+ return rComp.getPolygonIndex() < getPolygonIndex();
}
- bool importFromSvgD(B2DPolyPolygon& o_rPolyPolygon, const OUString& rSvgDStatement, bool bWrongPositionAfterZ)
+ bool importFromSvgD(
+ B2DPolyPolygon& o_rPolyPolygon,
+ const OUString& rSvgDStatement,
+ bool bHandleRelativeNextPointCompatible,
+ PointIndexSet* pHelpPointIndexSet)
{
o_rPolyPolygon.clear();
const sal_Int32 nLen(rSvgDStatement.getLength());
sal_Int32 nPos(0);
- bool bIsClosed(false);
double nLastX( 0.0 );
double nLastY( 0.0 );
B2DPolygon aCurrPoly;
// skip initial whitespace
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
while(nPos < nLen)
{
bool bRelative(false);
- bool bMoveTo(false);
const sal_Unicode aCurrChar(rSvgDStatement[nPos]);
+ if(o_rPolyPolygon.count() && !aCurrPoly.count() && !('m' == aCurrChar || 'M' == aCurrChar))
+ {
+ // we have a new sub-polygon starting, but without a 'moveto' command.
+ // this requires to add the current point as start point to the polygon
+ // (see SVG1.1 8.3.3 The "closepath" command)
+ aCurrPoly.append(B2DPoint(nLastX, nLastY));
+ }
+
switch(aCurrChar)
{
case 'z' :
case 'Z' :
{
+ // consume CurrChar and whitespace
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- // remember closed state of current polygon
- bIsClosed = true;
-
- // update current point - we're back at the start
- if( aCurrPoly.count() && !bWrongPositionAfterZ)
+ // create closed polygon and reset import values
+ if(aCurrPoly.count())
{
- const B2DPoint aFirst( aCurrPoly.getB2DPoint(0) );
- nLastX = aFirst.getX();
- nLastY = aFirst.getY();
+ if(!bHandleRelativeNextPointCompatible)
+ {
+ // SVG defines that "the next subpath starts at the
+ // same initial point as the current subpath", so set the
+ // current point if we do not need to be compatible
+ nLastX = aCurrPoly.getB2DPoint(0).getX();
+ nLastY = aCurrPoly.getB2DPoint(0).getY();
+ }
+
+ aCurrPoly.setClosed(true);
+ o_rPolyPolygon.append(aCurrPoly);
+ aCurrPoly.clear();
}
+
break;
}
case 'm' :
case 'M' :
{
- bMoveTo = true;
- // FALLTHROUGH intended
+ // create non-closed polygon and reset import values
+ if(aCurrPoly.count())
+ {
+ o_rPolyPolygon.append(aCurrPoly);
+ aCurrPoly.clear();
+ }
+
+ // FALLTHROUGH intended to add coordinate data as 1st point of new polygon
}
case 'l' :
case 'L' :
@@ -254,37 +118,16 @@ namespace basegfx
bRelative = true;
}
- if(bMoveTo)
- {
- // new polygon start, finish old one
- if(aCurrPoly.count())
- {
- // add current polygon
- if(bIsClosed)
- {
- // #i123465# no need to do the old closeWithGeometryChange
- // corerection on SVG polygons; this even may lead to wrong
- // results e.g. for marker processing
- aCurrPoly.setClosed(true);
- }
-
- o_rPolyPolygon.append(aCurrPoly);
-
- // reset import values
- bIsClosed = false;
- aCurrPoly.clear();
- }
- }
-
+ // consume CurrChar and whitespace
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -310,13 +153,13 @@ namespace basegfx
case 'H' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY(nLastY);
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -340,13 +183,13 @@ namespace basegfx
case 'V' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX(nLastX), nY;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -370,17 +213,17 @@ namespace basegfx
case 'S' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
double nX2, nY2;
- if(!lcl_importDoubleAndSpaces(nX2, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY2, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX2, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY2, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -429,20 +272,20 @@ namespace basegfx
case 'C' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
double nX1, nY1;
double nX2, nY2;
- if(!lcl_importDoubleAndSpaces(nX1, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY1, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nX2, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY2, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX1, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY1, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX2, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY2, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -479,17 +322,17 @@ namespace basegfx
case 'Q' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
double nX1, nY1;
- if(!lcl_importDoubleAndSpaces(nX1, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY1, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX1, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY1, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -530,14 +373,14 @@ namespace basegfx
case 'T' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -604,21 +447,21 @@ namespace basegfx
case 'A' :
{
nPos++;
- lcl_skipSpaces(nPos, rSvgDStatement, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgDStatement, nLen);
- while(nPos < nLen && lcl_isOnNumberChar(rSvgDStatement, nPos))
+ while(nPos < nLen && ::basegfx::internal::lcl_isOnNumberChar(rSvgDStatement, nPos))
{
double nX, nY;
double fRX, fRY, fPhi;
sal_Int32 bLargeArcFlag, bSweepFlag;
- if(!lcl_importDoubleAndSpaces(fRX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(fRY, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(fPhi, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importFlagAndSpaces(bLargeArcFlag, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importFlagAndSpaces(bSweepFlag, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(fRX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(fRY, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(fPhi, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importFlagAndSpaces(bLargeArcFlag, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importFlagAndSpaces(bSweepFlag, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgDStatement, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgDStatement, nLen)) return false;
if(bRelative)
{
@@ -749,7 +592,22 @@ namespace basegfx
// if we swapped angles above
if( !bSweepFlag )
aSegment.flip();
+
+ // remember PointIndex of evtl. added pure helper points
+ sal_uInt32 nPointIndex(aCurrPoly.count() + 1);
aCurrPoly.append(aSegment);
+
+ // if asked for, mark pure helper points by adding them to the index list of
+ // helper points
+ if(pHelpPointIndexSet && aCurrPoly.count() > 1)
+ {
+ const sal_uInt32 nPolyIndex(o_rPolyPolygon.count());
+
+ for(;nPointIndex + 1 < aCurrPoly.count(); nPointIndex++)
+ {
+ pHelpPointIndexSet->insert(PointIndex(nPolyIndex, nPointIndex));
+ }
+ }
}
// set last position
@@ -769,17 +627,9 @@ namespace basegfx
}
}
+ // if there is polygon data, create non-closed polygon
if(aCurrPoly.count())
{
- // end-process last poly
- if(bIsClosed)
- {
- // #i123465# no need to do the old closeWithGeometryChange
- // corerection on SVG polygons; this even may lead to wrong
- // results e.g. for marker processing
- aCurrPoly.setClosed(true);
- }
-
o_rPolyPolygon.append(aCurrPoly);
}
@@ -795,27 +645,51 @@ namespace basegfx
double nX, nY;
// skip initial whitespace
- lcl_skipSpaces(nPos, rSvgPointsAttribute, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgPointsAttribute, nLen);
while(nPos < nLen)
{
- if(!lcl_importDoubleAndSpaces(nX, nPos, rSvgPointsAttribute, nLen)) return false;
- if(!lcl_importDoubleAndSpaces(nY, nPos, rSvgPointsAttribute, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nX, nPos, rSvgPointsAttribute, nLen)) return false;
+ if(!::basegfx::internal::lcl_importDoubleAndSpaces(nY, nPos, rSvgPointsAttribute, nLen)) return false;
// add point
o_rPoly.append(B2DPoint(nX, nY));
// skip to next number, or finish
- lcl_skipSpaces(nPos, rSvgPointsAttribute, nLen);
+ ::basegfx::internal::lcl_skipSpaces(nPos, rSvgPointsAttribute, nLen);
}
return true;
}
+ OUString exportToSvgPoints( const B2DPolygon& rPoly )
+ {
+ OSL_ENSURE(!rPoly.areControlPointsUsed(), "exportToSvgPoints: Only non-bezier polygons allowed (!)");
+ const sal_uInt32 nPointCount(rPoly.count());
+ OUStringBuffer aResult;
+
+ for(sal_uInt32 a(0); a < nPointCount; a++)
+ {
+ const basegfx::B2DPoint aPoint(rPoly.getB2DPoint(a));
+
+ if(a)
+ {
+ aResult.append(sal_Unicode(' '));
+ }
+
+ ::basegfx::internal::lcl_putNumberChar(aResult, aPoint.getX());
+ aResult.append(sal_Unicode(','));
+ ::basegfx::internal::lcl_putNumberChar(aResult, aPoint.getY());
+ }
+
+ return aResult.makeStringAndClear();
+ }
+
OUString exportToSvgD(
const B2DPolyPolygon& rPolyPolygon,
bool bUseRelativeCoordinates,
- bool bDetectQuadraticBeziers)
+ bool bDetectQuadraticBeziers,
+ bool bHandleRelativeNextPointCompatible)
{
const sal_uInt32 nCount(rPolyPolygon.count());
OUStringBuffer aResult;
@@ -835,10 +709,21 @@ namespace basegfx
// handle polygon start point
B2DPoint aEdgeStart(aPolygon.getB2DPoint(0));
- aResult.append(lcl_getCommand('M', 'm', bUseRelativeCoordinates));
- lcl_putNumberCharWithSpace(aResult, aEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- aLastSVGCommand = lcl_getCommand('L', 'l', bUseRelativeCoordinates);
+ bool bUseRelativeCoordinatesForFirstPoint(bUseRelativeCoordinates);
+
+ if(bHandleRelativeNextPointCompatible)
+ {
+ // To get around the error that the start point for the next polygon is the
+ // start point of the current one (and not the last as it was handled up to now)
+ // do force to write an absolute 'M' command as start for the next polygon
+ bUseRelativeCoordinatesForFirstPoint = false;
+ }
+
+ // Write 'moveto' and the 1st coordinates, set aLastSVGCommand to 'lineto'
+ aResult.append(::basegfx::internal::lcl_getCommand('M', 'm', bUseRelativeCoordinatesForFirstPoint));
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinatesForFirstPoint);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinatesForFirstPoint);
+ aLastSVGCommand = ::basegfx::internal::lcl_getCommand('L', 'l', bUseRelativeCoordinatesForFirstPoint);
aCurrentSVGPosition = aEdgeStart;
for(sal_uInt32 nIndex(0); nIndex < nEdgeCount; nIndex++)
@@ -892,7 +777,7 @@ namespace basegfx
// approximately equal, export as quadratic bezier
if(bSymmetricAtEdgeStart)
{
- const sal_Unicode aCommand(lcl_getCommand('T', 't', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('T', 't', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -900,14 +785,14 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aLastSVGCommand = aCommand;
aCurrentSVGPosition = aEdgeEnd;
}
else
{
- const sal_Unicode aCommand(lcl_getCommand('Q', 'q', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('Q', 'q', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -915,10 +800,10 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aLeft.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aLeft.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aLeft.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aLeft.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aLastSVGCommand = aCommand;
aCurrentSVGPosition = aEdgeEnd;
}
@@ -928,7 +813,7 @@ namespace basegfx
// export as cubic bezier
if(bSymmetricAtEdgeStart)
{
- const sal_Unicode aCommand(lcl_getCommand('S', 's', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('S', 's', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -936,16 +821,16 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aLastSVGCommand = aCommand;
aCurrentSVGPosition = aEdgeEnd;
}
else
{
- const sal_Unicode aCommand(lcl_getCommand('C', 'c', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('C', 'c', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -953,12 +838,12 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aControlEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aControlEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aLastSVGCommand = aCommand;
aCurrentSVGPosition = aEdgeEnd;
}
@@ -984,7 +869,7 @@ namespace basegfx
else if(bXEqual)
{
// export as vertical line
- const sal_Unicode aCommand(lcl_getCommand('V', 'v', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('V', 'v', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -992,13 +877,13 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aCurrentSVGPosition = aEdgeEnd;
}
else if(bYEqual)
{
// export as horizontal line
- const sal_Unicode aCommand(lcl_getCommand('H', 'h', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('H', 'h', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -1006,13 +891,13 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
aCurrentSVGPosition = aEdgeEnd;
}
else
{
// export as line
- const sal_Unicode aCommand(lcl_getCommand('L', 'l', bUseRelativeCoordinates));
+ const sal_Unicode aCommand(::basegfx::internal::lcl_getCommand('L', 'l', bUseRelativeCoordinates));
if(aLastSVGCommand != aCommand)
{
@@ -1020,8 +905,8 @@ namespace basegfx
aLastSVGCommand = aCommand;
}
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ ::basegfx::internal::lcl_putNumberCharWithSpace(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
aCurrentSVGPosition = aEdgeEnd;
}
}
@@ -1034,8 +919,13 @@ namespace basegfx
// close path if closed poly (Z and z are equivalent here, but looks nicer when case is matched)
if(aPolygon.isClosed())
{
- aResult.append(lcl_getCommand('Z', 'z', bUseRelativeCoordinates));
- // return to first point
+ aResult.append(::basegfx::internal::lcl_getCommand('Z', 'z', bUseRelativeCoordinates));
+ }
+
+ if(!bHandleRelativeNextPointCompatible)
+ {
+ // SVG defines that "the next subpath starts at the same initial point as the current subpath",
+ // so set aCurrentSVGPosition to the 1st point of the current, now ended and written path
aCurrentSVGPosition = aPolygon.getB2DPoint(0);
}
}
diff --git a/basegfx/source/polygon/b3dpolypolygontools.cxx b/basegfx/source/polygon/b3dpolypolygontools.cxx
index dd7fa412235e..83241d8bfa87 100644
--- a/basegfx/source/polygon/b3dpolypolygontools.cxx
+++ b/basegfx/source/polygon/b3dpolypolygontools.cxx
@@ -26,6 +26,7 @@
#include <numeric>
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <basegfx/numeric/ftools.hxx>
+#include <com/sun/star/drawing/DoubleSequence.hpp>
//////////////////////////////////////////////////////////////////////////////
// predefines
@@ -483,6 +484,158 @@ namespace basegfx
}
}
+ //////////////////////////////////////////////////////////////////////
+ // comparators with tolerance for 3D PolyPolygons
+
+ bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB, const double& rfSmallValue)
+ {
+ const sal_uInt32 nPolygonCount(rCandidateA.count());
+
+ if(nPolygonCount != rCandidateB.count())
+ return false;
+
+ for(sal_uInt32 a(0); a < nPolygonCount; a++)
+ {
+ const B3DPolygon aCandidate(rCandidateA.getB3DPolygon(a));
+
+ if(!equal(aCandidate, rCandidateB.getB3DPolygon(a), rfSmallValue))
+ return false;
+ }
+
+ return true;
+ }
+
+ bool equal(const B3DPolyPolygon& rCandidateA, const B3DPolyPolygon& rCandidateB)
+ {
+ const double fSmallValue(fTools::getSmallValue());
+
+ return equal(rCandidateA, rCandidateB, fSmallValue);
+ }
+
+/// converters for com::sun::star::drawing::PolyPolygonShape3D
+ B3DPolyPolygon UnoPolyPolygonShape3DToB3DPolyPolygon(
+ const com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DSource,
+ bool bCheckClosed)
+ {
+ B3DPolyPolygon aRetval;
+ const sal_Int32 nOuterSequenceCount(rPolyPolygonShape3DSource.SequenceX.getLength());
+
+ if(nOuterSequenceCount)
+ {
+ OSL_ENSURE(nOuterSequenceCount == rPolyPolygonShape3DSource.SequenceY.getLength()
+ && nOuterSequenceCount == rPolyPolygonShape3DSource.SequenceZ.getLength(),
+ "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have the same length (!)");
+
+ const com::sun::star::drawing::DoubleSequence* pInnerSequenceX = rPolyPolygonShape3DSource.SequenceX.getConstArray();
+ const com::sun::star::drawing::DoubleSequence* pInnerSequenceY = rPolyPolygonShape3DSource.SequenceY.getConstArray();
+ const com::sun::star::drawing::DoubleSequence* pInnerSequenceZ = rPolyPolygonShape3DSource.SequenceZ.getConstArray();
+
+ for(sal_Int32 a(0); a < nOuterSequenceCount; a++)
+ {
+ basegfx::B3DPolygon aNewPolygon;
+ const sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
+ OSL_ENSURE(nInnerSequenceCount == pInnerSequenceY->getLength()
+ && nInnerSequenceCount == pInnerSequenceZ->getLength(),
+ "UnoPolyPolygonShape3DToB3DPolygon: Not all double sequences have the same length (!)");
+
+ const double* pArrayX = pInnerSequenceX->getConstArray();
+ const double* pArrayY = pInnerSequenceY->getConstArray();
+ const double* pArrayZ = pInnerSequenceZ->getConstArray();
+
+ for(sal_Int32 b(0); b < nInnerSequenceCount; b++)
+ {
+ aNewPolygon.append(basegfx::B3DPoint(*pArrayX++,*pArrayY++,*pArrayZ++));
+ }
+
+ pInnerSequenceX++;
+ pInnerSequenceY++;
+ pInnerSequenceZ++;
+
+ // #i101520# correction is needed for imported polygons of old format,
+ // see callers
+ if(bCheckClosed)
+ {
+ basegfx::tools::checkClosed(aNewPolygon);
+ }
+
+ aRetval.append(aNewPolygon);
+ }
+ }
+
+ return aRetval;
+ }
+
+ void B3DPolyPolygonToUnoPolyPolygonShape3D(
+ const B3DPolyPolygon& rPolyPolygonSource,
+ com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DRetval)
+ {
+ const sal_uInt32 nPolygonCount(rPolyPolygonSource.count());
+
+ if(nPolygonCount)
+ {
+ rPolyPolygonShape3DRetval.SequenceX.realloc(nPolygonCount);
+ rPolyPolygonShape3DRetval.SequenceY.realloc(nPolygonCount);
+ rPolyPolygonShape3DRetval.SequenceZ.realloc(nPolygonCount);
+
+ com::sun::star::drawing::DoubleSequence* pOuterSequenceX = rPolyPolygonShape3DRetval.SequenceX.getArray();
+ com::sun::star::drawing::DoubleSequence* pOuterSequenceY = rPolyPolygonShape3DRetval.SequenceY.getArray();
+ com::sun::star::drawing::DoubleSequence* pOuterSequenceZ = rPolyPolygonShape3DRetval.SequenceZ.getArray();
+
+ for(sal_uInt32 a(0); a < nPolygonCount; a++)
+ {
+ const basegfx::B3DPolygon aPoly(rPolyPolygonSource.getB3DPolygon(a));
+ const sal_uInt32 nPointCount(aPoly.count());
+
+ if(nPointCount)
+ {
+ const bool bIsClosed(aPoly.isClosed());
+ const sal_uInt32 nTargetCount(bIsClosed ? nPointCount + 1 : nPointCount);
+ pOuterSequenceX->realloc(nTargetCount);
+ pOuterSequenceY->realloc(nTargetCount);
+ pOuterSequenceZ->realloc(nTargetCount);
+
+ double* pInnerSequenceX = pOuterSequenceX->getArray();
+ double* pInnerSequenceY = pOuterSequenceY->getArray();
+ double* pInnerSequenceZ = pOuterSequenceZ->getArray();
+
+ for(sal_uInt32 b(0); b < nPointCount; b++)
+ {
+ const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(b));
+
+ *pInnerSequenceX++ = aPoint.getX();
+ *pInnerSequenceY++ = aPoint.getY();
+ *pInnerSequenceZ++ = aPoint.getZ();
+ }
+
+ if(bIsClosed)
+ {
+ const basegfx::B3DPoint aPoint(aPoly.getB3DPoint(0));
+
+ *pInnerSequenceX++ = aPoint.getX();
+ *pInnerSequenceY++ = aPoint.getY();
+ *pInnerSequenceZ++ = aPoint.getZ();
+ }
+ }
+ else
+ {
+ pOuterSequenceX->realloc(0);
+ pOuterSequenceY->realloc(0);
+ pOuterSequenceZ->realloc(0);
+ }
+
+ pOuterSequenceX++;
+ pOuterSequenceY++;
+ pOuterSequenceZ++;
+ }
+ }
+ else
+ {
+ rPolyPolygonShape3DRetval.SequenceX.realloc(0);
+ rPolyPolygonShape3DRetval.SequenceY.realloc(0);
+ rPolyPolygonShape3DRetval.SequenceZ.realloc(0);
+ }
+ }
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/basegfx/source/tools/stringconversiontools.cxx b/basegfx/source/tools/stringconversiontools.cxx
new file mode 100644
index 000000000000..bc5cfb240745
--- /dev/null
+++ b/basegfx/source/tools/stringconversiontools.cxx
@@ -0,0 +1,169 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <stringconversiontools.hxx>
+#include <rtl/math.hxx>
+
+namespace basegfx
+{
+ namespace internal
+ {
+ void lcl_skipSpaces(sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen)
+ {
+ while( io_rPos < nLen &&
+ sal_Unicode(' ') == rStr[io_rPos] )
+ {
+ ++io_rPos;
+ }
+ }
+
+ void lcl_skipSpacesAndCommas(sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen)
+ {
+ while(io_rPos < nLen
+ && (sal_Unicode(' ') == rStr[io_rPos] || sal_Unicode(',') == rStr[io_rPos]))
+ {
+ ++io_rPos;
+ }
+ }
+
+ bool lcl_getDoubleChar(double& o_fRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr)
+ {
+ sal_Unicode aChar( rStr[io_rPos] );
+ OUStringBuffer sNumberString;
+ bool separator_seen=false;
+
+ if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
+ {
+ sNumberString.append(rStr[io_rPos]);
+ aChar = rStr[++io_rPos];
+ }
+
+ while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
+ || (!separator_seen && sal_Unicode('.') == aChar))
+ {
+ if (sal_Unicode('.') == aChar) separator_seen = true;
+ sNumberString.append(rStr[io_rPos]);
+ io_rPos++;
+ aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
+ }
+
+ if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
+ {
+ sNumberString.append(rStr[io_rPos]);
+ io_rPos++;
+ aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
+
+ if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
+ {
+ sNumberString.append(rStr[io_rPos]);
+ io_rPos++;
+ aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
+ }
+
+ while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
+ {
+ sNumberString.append(rStr[io_rPos]);
+ io_rPos++;
+ aChar = io_rPos < rStr.getLength() ? rStr[io_rPos] : 0;
+ }
+ }
+
+ if(sNumberString.getLength())
+ {
+ rtl_math_ConversionStatus eStatus;
+ o_fRetval = ::rtl::math::stringToDouble( sNumberString.makeStringAndClear(),
+ (sal_Unicode)('.'),
+ (sal_Unicode)(','),
+ &eStatus,
+ NULL );
+ return ( eStatus == rtl_math_ConversionStatus_Ok );
+ }
+
+ return false;
+ }
+
+ bool lcl_importDoubleAndSpaces( double& o_fRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen )
+ {
+ if( !lcl_getDoubleChar(o_fRetval, io_rPos, rStr) )
+ return false;
+
+ lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
+
+ return true;
+ }
+
+ bool lcl_importFlagAndSpaces(sal_Int32& o_nRetval,
+ sal_Int32& io_rPos,
+ const OUString& rStr,
+ const sal_Int32 nLen)
+ {
+ sal_Unicode aChar( rStr[io_rPos] );
+
+ if(sal_Unicode('0') == aChar)
+ {
+ o_nRetval = 0;
+ ++io_rPos;
+ }
+ else if (sal_Unicode('1') == aChar)
+ {
+ o_nRetval = 1;
+ ++io_rPos;
+ }
+ else
+ return false;
+
+ lcl_skipSpacesAndCommas(io_rPos, rStr, nLen);
+
+ return true;
+ }
+
+ void lcl_putNumberCharWithSpace( OUStringBuffer& rStr,
+ double fValue,
+ double fOldValue,
+ bool bUseRelativeCoordinates )
+ {
+ if( bUseRelativeCoordinates )
+ fValue -= fOldValue;
+
+ const sal_Int32 aLen( rStr.getLength() );
+ if(aLen)
+ {
+ if( lcl_isOnNumberChar(rStr[aLen - 1], false) &&
+ fValue >= 0.0 )
+ {
+ rStr.append( sal_Unicode(' ') );
+ }
+ }
+
+ lcl_putNumberChar(rStr, fValue);
+ }
+
+ } // namespace internal
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/test/basegfx2d.cxx b/basegfx/test/basegfx2d.cxx
index 67ecb3e32d0b..15446780d6d6 100644
--- a/basegfx/test/basegfx2d.cxx
+++ b/basegfx/test/basegfx2d.cxx
@@ -142,23 +142,20 @@ public:
OUString aExport;
CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D",
- tools::importFromSvgD( aPoly,
- aPath0 ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aPath0, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
const char* sExportString = "m10 10h-20v-20h20z";
CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D",
!aExport.compareToAscii(sExportString) );
CPPUNIT_ASSERT_MESSAGE("importing simple rectangle from SVG-D (round-trip",
- tools::importFromSvgD( aPoly,
- aExport ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aExport, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
CPPUNIT_ASSERT_MESSAGE("exporting rectangle to SVG-D (round-trip)",
!aExport.compareToAscii(sExportString));
CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D",
- tools::importFromSvgD( aPoly,
- aPath1 ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aPath1, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
// Adaptions for B2DPolygon bezier change (see #i77162#):
//
@@ -185,11 +182,11 @@ public:
// a 2nd good test is that re-importing of aExport has to create the same
// B2DPolPolygon again:
B2DPolyPolygon aReImport;
- CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport));
+ CPPUNIT_ASSERT_MESSAGE("importing simple bezier polygon from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0));
CPPUNIT_ASSERT_MESSAGE("re-imported polygon needs to be identical", aReImport == aPoly);
- CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2 ));
- aExport = tools::exportToSvgD( aPoly );
+ CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D", tools::importFromSvgD( aPoly, aPath2, false, NULL));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
// Adaptions for B2DPolygon bezier change (see #i77162#):
//
@@ -205,22 +202,20 @@ public:
"8 752-224 1128-21 101-31 183-31 245 0 39 9 70 26 93 17 24 39 36 67 36 145 0 279-80 400-240s182-365 182-615c0-2"
"88-107-533-322-734s-487-301-816-301c-395 0-715 124-960 373s-368 569-368 958q0 577.5 357 900c237 216 557 324 95"
"8 325 189-1 389-27 600-77 211-52 378-110 503-174q40.5 105 81 210z";
- CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport));
+ CPPUNIT_ASSERT_MESSAGE("re-importing '@' from SVG-D", tools::importFromSvgD( aReImport, aExport, false, 0));
CPPUNIT_ASSERT_MESSAGE("re-imported '@' needs to be identical", aReImport == aPoly);
CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D", !aExport.compareToAscii(sExportString1));
CPPUNIT_ASSERT_MESSAGE("importing '@' from SVG-D (round-trip",
- tools::importFromSvgD( aPoly,
- aExport ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aExport, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
CPPUNIT_ASSERT_MESSAGE("exporting '@' to SVG-D (round-trip)",
!aExport.compareToAscii(sExportString1));
CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D",
- tools::importFromSvgD( aPoly,
- aPath3 ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aPath3, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
const char* sExportString2 =
"m1598 125h306v2334h-306v-1105h-1293v1105h-305v-2334h305v973h1293"
"zm2159 1015 78-44 85 235-91 47-91 40-90 34-90 29-89 21-88 16-88 10-88 3-102-4-97"
@@ -245,15 +240,14 @@ public:
CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D",
!aExport.compareToAscii(sExportString2));
CPPUNIT_ASSERT_MESSAGE("importing complex polygon from SVG-D (round-trip",
- tools::importFromSvgD( aPoly,
- aExport ));
- aExport = tools::exportToSvgD( aPoly );
+ tools::importFromSvgD( aPoly, aExport, false, 0 ));
+ aExport = tools::exportToSvgD( aPoly, true, true, false );
CPPUNIT_ASSERT_MESSAGE("exporting complex polygon to SVG-D (round-trip)",
!aExport.compareToAscii(sExportString2));
const B2DPolygon aRect(
tools::createPolygonFromRect( B2DRange(0.0,0.0,4000.0,4000.0) ));
- aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false);
+ aExport = tools::exportToSvgD( B2DPolyPolygon(aRect), false, false, false );
const char* sExportStringRect = "M0 0H4000V4000H0Z";
CPPUNIT_ASSERT_MESSAGE("exporting to rectangle svg-d string",
diff --git a/basegfx/test/boxclipper.cxx b/basegfx/test/boxclipper.cxx
index a296871d7fe9..bb02dc521d48 100644
--- a/basegfx/test/boxclipper.cxx
+++ b/basegfx/test/boxclipper.cxx
@@ -165,7 +165,7 @@ public:
B2DPolyPolygon randomPoly;
tools::importFromSvgD(
randomPoly,
- OUString::createFromAscii(randomSvg));
+ OUString::createFromAscii(randomSvg), false, 0);
std::for_each(randomPoly.begin(),
randomPoly.end(),
boost::bind(
@@ -240,16 +240,15 @@ public:
B2DPolyPolygon aTmp1;
CPPUNIT_ASSERT_MESSAGE(sName,
tools::importFromSvgD(
- aTmp1,
- OUString::createFromAscii(sSvg)));
+ aTmp1, OUString::createFromAscii(sSvg), false, 0));
const OUString aSvg=
- tools::exportToSvgD(toTest.solveCrossovers());
+ tools::exportToSvgD(toTest.solveCrossovers(), true, true, false);
B2DPolyPolygon aTmp2;
CPPUNIT_ASSERT_MESSAGE(sName,
tools::importFromSvgD(
- aTmp2,
- aSvg));
+ aTmp2, aSvg, false, 0));
+
CPPUNIT_ASSERT_MESSAGE(
sName,
normalizePoly(aTmp2) == normalizePoly(aTmp1));
@@ -321,7 +320,7 @@ public:
#if OSL_DEBUG_LEVEL > 2
fprintf(stderr, "%s - svg:d=\"%s\"\n",
pName, OUStringToOString(
- basegfx::tools::exportToSvgD(rPoly),
+ basegfx::tools::exportToSvgD(rPoly, , true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
#endif
}
@@ -365,15 +364,14 @@ public:
fprintf(stderr, "%s input - svg:d=\"%s\"\n",
pName, OUStringToOString(
basegfx::tools::exportToSvgD(
- genericClip),
+ genericClip, , true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
#endif
const B2DPolyPolygon boxClipResult=rRange.solveCrossovers();
const OUString boxClipSvg(
basegfx::tools::exportToSvgD(
- normalizePoly(
- boxClipResult)));
+ normalizePoly(boxClipResult), true, true, false));
#if OSL_DEBUG_LEVEL > 2
fprintf(stderr, "%s boxclipper - svg:d=\"%s\"\n",
pName, OUStringToOString(
@@ -384,8 +382,7 @@ public:
genericClip = tools::solveCrossovers(genericClip);
const OUString genericClipSvg(
basegfx::tools::exportToSvgD(
- normalizePoly(
- genericClip)));
+ normalizePoly(genericClip), true, true, false));
#if OSL_DEBUG_LEVEL > 2
fprintf(stderr, "%s genclipper - svg:d=\"%s\"\n",
pName, OUStringToOString(
diff --git a/basegfx/test/clipstate.cxx b/basegfx/test/clipstate.cxx
index f2b0ef0e94b7..ffdc35397fb8 100644
--- a/basegfx/test/clipstate.cxx
+++ b/basegfx/test/clipstate.cxx
@@ -95,23 +95,21 @@ public:
#if OSL_DEBUG_LEVEL > 2
fprintf(stderr, "%s - svg:d=\"%s\"\n",
sName, OUStringToOString(
- basegfx::tools::exportToSvgD(toTest.getClipPoly()),
+ basegfx::tools::exportToSvgD(toTest.getClipPoly(), true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
#endif
B2DPolyPolygon aTmp1;
CPPUNIT_ASSERT_MESSAGE(sName,
tools::importFromSvgD(
- aTmp1,
- OUString::createFromAscii(sSvg)));
+ aTmp1, OUString::createFromAscii(sSvg), false, 0));
const OUString aSvg=
- tools::exportToSvgD(toTest.getClipPoly());
+ tools::exportToSvgD(toTest.getClipPoly(), true, true, false);
B2DPolyPolygon aTmp2;
CPPUNIT_ASSERT_MESSAGE(sName,
tools::importFromSvgD(
- aTmp2,
- aSvg));
+ aTmp2, aSvg, false, 0));
CPPUNIT_ASSERT_MESSAGE(
sName,
@@ -142,8 +140,7 @@ public:
B2DPolyPolygon aTmp1;
tools::importFromSvgD(
- aTmp1,
- OUString::createFromAscii(unionSvg));
+ aTmp1, OUString::createFromAscii(unionSvg), false, 0);
aMixedClip.intersectPolyPolygon(aTmp1);
aMixedClip.subtractRange(B2DRange(-20,-150,20,0));
diff --git a/basegfx/test/genericclipper.cxx b/basegfx/test/genericclipper.cxx
index c1af17d369c5..8a428dd725e4 100644
--- a/basegfx/test/genericclipper.cxx
+++ b/basegfx/test/genericclipper.cxx
@@ -79,12 +79,12 @@ public:
fprintf(stderr, "%s input LHS - svg:d=\"%s\"\n",
pName, OUStringToOString(
basegfx::tools::exportToSvgD(
- aSelfIntersect),
+ aSelfIntersect, true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
fprintf(stderr, "%s input RHS - svg:d=\"%s\"\n",
pName, OUStringToOString(
basegfx::tools::exportToSvgD(
- aRect),
+ aRect, true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
#endif
@@ -94,14 +94,14 @@ public:
#if OSL_DEBUG_LEVEL > 2
fprintf(stderr, "%s - svg:d=\"%s\"\n",
pName, OUStringToOString(
- basegfx::tools::exportToSvgD(aRes),
+ basegfx::tools::exportToSvgD(aRes, true, true, false),
RTL_TEXTENCODING_UTF8).getStr() );
#endif
OUString aValid=OUString::createFromAscii(pValidSvgD);
CPPUNIT_ASSERT_MESSAGE(pName,
- basegfx::tools::exportToSvgD(aRes) == aValid);
+ basegfx::tools::exportToSvgD(aRes, true, true, false) == aValid);
}
void validateOr()
@@ -136,13 +136,13 @@ public:
OUString aValid=OUString::createFromAscii(pValidSvgD);
B2DPolyPolygon aInputPoly, aValidPoly;
- tools::importFromSvgD(aInputPoly, aInput);
- tools::importFromSvgD(aValidPoly, aValid);
+ tools::importFromSvgD(aInputPoly, aInput, false, NULL);
+ tools::importFromSvgD(aValidPoly, aValid, false, NULL);
CPPUNIT_ASSERT_MESSAGE(
pName,
basegfx::tools::exportToSvgD(
- tools::solveCrossovers(aInputPoly)) == aValid);
+ tools::solveCrossovers(aInputPoly), true, true, false) == aValid);
}
void checkCrossoverSolver()
diff --git a/canvas/source/tools/surfaceproxy.cxx b/canvas/source/tools/surfaceproxy.cxx
index c1f857a93f64..e2510b4e2b62 100644
--- a/canvas/source/tools/surfaceproxy.cxx
+++ b/canvas/source/tools/surfaceproxy.cxx
@@ -150,11 +150,11 @@ namespace canvas
OSL_TRACE( "Original clip polygon: %s\n"
"Triangulated polygon: %s\n",
OUStringToOString(
- basegfx::tools::exportToSvgD( rClipPoly ),
+ basegfx::tools::exportToSvgD( rClipPoly, true, true, false ),
RTL_TEXTENCODING_ASCII_US).getStr(),
OUStringToOString(
basegfx::tools::exportToSvgD(
- basegfx::B2DPolyPolygon(rTriangulatedPolygon) ),
+ basegfx::B2DPolyPolygon(rTriangulatedPolygon), true, true, false ),
RTL_TEXTENCODING_ASCII_US).getStr() );
#endif
diff --git a/filter/source/svg/svgreader.cxx b/filter/source/svg/svgreader.cxx
index f1f9eedc249c..cd4a3931a0b6 100644
--- a/filter/source/svg/svgreader.cxx
+++ b/filter/source/svg/svgreader.cxx
@@ -1244,7 +1244,7 @@ struct ShapeWritingVisitor
+OUString::number(y1)+"L"+OUString::number(x2)+","
+OUString::number(y2);
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD(aPoly, sLinePath);
+ basegfx::tools::importFromSvgD(aPoly, sLinePath, false, NULL);
writePathShape(xAttrs,
xUnoAttrs,
@@ -1334,7 +1334,7 @@ struct ShapeWritingVisitor
{
OUString sPath = xElem->hasAttribute("d") ? xElem->getAttribute("d") : "";
basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD(aPoly, sPath);
+ basegfx::tools::importFromSvgD(aPoly, sPath, false, NULL);
writePathShape(xAttrs,
xUnoAttrs,
@@ -1668,7 +1668,8 @@ struct ShapeWritingVisitor
xAttrs->AddAttribute( "svg:d", basegfx::tools::exportToSvgD(
aPolys[i],
false, // no relative coords. causes rounding errors
- false )); // no quad bezier detection. crashes older versions.
+ false, // no quad bezier detection. crashes older versions.
+ false ));
mxDocumentHandler->startElement("draw:path", xUnoAttrs);
mxDocumentHandler->endElement("draw:path");
}
diff --git a/include/basegfx/polygon/b2dpolygontools.hxx b/include/basegfx/polygon/b2dpolygontools.hxx
index 6aa96927edd7..73137568c703 100644
--- a/include/basegfx/polygon/b2dpolygontools.hxx
+++ b/include/basegfx/polygon/b2dpolygontools.hxx
@@ -25,6 +25,8 @@
#include <basegfx/range/b2drectangle.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b3dpolygon.hxx>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
#include <vector>
#include <basegfx/basegfxdllapi.h>
@@ -451,6 +453,58 @@ namespace basegfx
/// polygon path data. Take into account all stuff like closed state, zero-length edges and others.
BASEGFX_DLLPUBLIC B2DVector getTangentLeavingPoint(const B2DPolygon& rCandidate, sal_uInt32 nIndex);
+ /// converters for com::sun::star::drawing::PointSequence
+ BASEGFX_DLLPUBLIC B2DPolygon UnoPointSequenceToB2DPolygon(
+ const com::sun::star::drawing::PointSequence& rPointSequenceSource,
+ bool bCheckClosed = true);
+ BASEGFX_DLLPUBLIC void B2DPolygonToUnoPointSequence(
+ const B2DPolygon& rPolygon,
+ com::sun::star::drawing::PointSequence& rPointSequenceRetval);
+
+ /* converters for com::sun::star::drawing::PointSequence and
+ com::sun::star::drawing::FlagSequence to B2DPolygon (curved polygons)
+ */
+ B2DPolygon UnoPolygonBezierCoordsToB2DPolygon(
+ const com::sun::star::drawing::PointSequence& rPointSequenceSource,
+ const com::sun::star::drawing::FlagSequence& rFlagSequenceSource,
+ bool bCheckClosed = true);
+ void B2DPolygonToUnoPolygonBezierCoords(
+ const B2DPolygon& rPolyPolygon,
+ com::sun::star::drawing::PointSequence& rPointSequenceRetval,
+ com::sun::star::drawing::FlagSequence& rFlagSequenceRetval);
+
+ /** Read poly-polygon from SVG.
+
+ This function imports a poly-polygon from an SVG points
+ attribute (a plain list of coordinate pairs).
+
+ @param o_rPoly
+ The output polygon. Note that svg:points can only define a
+ single polygon
+
+ @param rSvgPointsAttribute
+ A valid SVG points attribute string
+
+ @return true, if the string was successfully parsed
+ */
+ BASEGFX_DLLPUBLIC bool importFromSvgPoints( B2DPolygon& o_rPoly,
+ const OUString& rSvgPointsAttribute );
+
+ /** Write poly-polygon to SVG.
+
+ This function imports a non-bezier polygon to SVG points
+ (a plain list of coordinate pairs).
+
+ @param rPoly
+ The polygon to export
+
+ @param rSvgPointsAttribute
+ A valid SVG points attribute string
+
+ @return true, if the string was successfully parsed
+ */
+ BASEGFX_DLLPUBLIC OUString exportToSvgPoints( const B2DPolygon& rPoly );
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/include/basegfx/polygon/b2dpolypolygontools.hxx b/include/basegfx/polygon/b2dpolypolygontools.hxx
index 521d07595f8a..182053bfbd90 100644
--- a/include/basegfx/polygon/b2dpolypolygontools.hxx
+++ b/include/basegfx/polygon/b2dpolypolygontools.hxx
@@ -24,7 +24,10 @@
#include <basegfx/vector/b2dvector.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <vector>
+#include <set>
#include <basegfx/basegfxdllapi.h>
@@ -100,6 +103,32 @@ namespace basegfx
// with distance fDistance and rounded edges (start and end point).
BASEGFX_DLLPUBLIC bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance);
+ /** Helper class to transport PointIndices to a PolyPolygon,
+ with an operator< for convenient sorting in a std::set usage
+ */
+ class BASEGFX_DLLPUBLIC SAL_WARN_UNUSED PointIndex
+ {
+ private:
+ sal_uInt32 mnPolygonIndex;
+ sal_uInt32 mnPointIndex;
+
+ public:
+ PointIndex(sal_uInt32 nPolygonIndex, sal_uInt32 nPointIndex)
+ : mnPolygonIndex(nPolygonIndex),
+ mnPointIndex(nPointIndex)
+ {}
+
+ sal_uInt32 getPolygonIndex() const { return mnPolygonIndex; }
+ sal_uInt32 getPointIndex() const { return mnPointIndex; }
+ bool operator<(const PointIndex& rComp) const;
+ };
+
+ /** the PointIndexSet itself; it allows to define a 'selection'of
+ points in a PolyPolygon by giving the polygon and point index.
+ Adding points double makes no sense, hence the std::set
+ */
+ typedef std::set< PointIndex > PointIndexSet;
+
/** Read poly-polygon from SVG.
This function imports a poly-polygon from an SVG-D
@@ -111,33 +140,29 @@ namespace basegfx
@param rSvgDAttribute
A valid SVG-D attribute string
- @param rWrongPositionAfterZ
- Indicates wheter the generator interprets wrongly
- the position in the path after Z or z elements
- https://bugs.freedesktop.org/show_bug.cgi?id=47406
-
- @return true, if the string was successfully parsed
- */
- BASEGFX_DLLPUBLIC bool importFromSvgD( B2DPolyPolygon& o_rPolyPoly,
- const OUString& rSvgDAttribute, bool bWrongPositionAfterZ = false );
-
- /** Read poly-polygon from SVG.
-
- This function imports a poly-polygon from an SVG points
- attribute (a plain list of coordinate pairs).
-
- @param o_rPoly
- The output polygon. Note that svg:points can only define a
- single polygon
-
- @param rSvgPointsAttribute
- A valid SVG points attribute string
+ @param bHandleRelativeNextPointCompatible
+ If set to true, the old error that after a relative 'z' command
+ the current point was not reset to the first point of the current
+ polygon is kept; this is needed to read odf files.
+ If false, pure svg is used; this is needed for svg import.
+
+ @param pHelpPointIndexSet
+ If given, all points created in the target PolyPolygon
+ which are only helper points are added here using their
+ point indices; this are currently points created from
+ import of the 'a' and 'A' svg:d statements which create
+ bezier curve info as representation and maybe points
+ which are no 'real' svg:d points, but helper points. It
+ is necessary to identify these e.g. when markers need to
+ be created in the svg import
@return true, if the string was successfully parsed
*/
- BASEGFX_DLLPUBLIC bool importFromSvgPoints( B2DPolygon& o_rPoly,
- const OUString& rSvgPointsAttribute );
-
+ BASEGFX_DLLPUBLIC bool importFromSvgD(
+ B2DPolyPolygon& o_rPolyPoly,
+ const OUString& rSvgDAttribute,
+ bool bHandleRelativeNextPointCompatible,
+ PointIndexSet* pHelpPointIndexSet);
// grow for polyPolygon. Move all geometry in each point in the direction of the normal in that point
// with the given amount. Value may be negative.
@@ -210,12 +235,20 @@ namespace basegfx
quadratic bezier segments. Note that the generated string
causes versions prior to OOo2.0 to crash.
+ @param bHandleRelativeNextPointCompatible
+ If set to true, the old error that after a relative 'z' command
+ the current point was not reset to the first point of the current
+ polygon is kept; this is needed to read odf files.
+ If false, pure svg is used; this is needed for svg import.
+
@return the generated SVG-D statement (the XML d attribute
value alone, without any "<path ...>" or "d="...")
*/
- BASEGFX_DLLPUBLIC OUString exportToSvgD( const B2DPolyPolygon& rPolyPoly,
- bool bUseRelativeCoordinates=true,
- bool bDetectQuadraticBeziers=true );
+ BASEGFX_DLLPUBLIC OUString exportToSvgD(
+ const B2DPolyPolygon& rPolyPoly,
+ bool bUseRelativeCoordinates,
+ bool bDetectQuadraticBeziers,
+ bool bHandleRelativeNextPointCompatible);
// #i76891# Try to remove existing curve segments if they are simply edges
BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate);
@@ -259,6 +292,22 @@ namespace basegfx
*/
BASEGFX_DLLPUBLIC bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate);
+ /// converters for com::sun::star::drawing::PointSequence
+ BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
+ const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
+ bool bCheckClosed = true);
+ BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPointSequenceSequence(
+ const B2DPolyPolygon& rPolyPolygon,
+ com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval);
+
+ /// converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
+ BASEGFX_DLLPUBLIC B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
+ const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
+ bool bCheckClosed = true);
+ BASEGFX_DLLPUBLIC void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ const B2DPolyPolygon& rPolyPolygon,
+ com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval);
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/include/basegfx/polygon/b3dpolypolygontools.hxx b/include/basegfx/polygon/b3dpolypolygontools.hxx
index 3b5011ddeeb3..24fb902e79cc 100644
--- a/include/basegfx/polygon/b3dpolypolygontools.hxx
+++ b/include/basegfx/polygon/b3dpolypolygontools.hxx
@@ -22,9 +22,10 @@
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dvector.hxx>
-#include <vector>
#include <basegfx/numeric/ftools.hxx>
#include <basegfx/point/b3dpoint.hxx>
+#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
+#include <vector>
#include <basegfx/basegfxdllapi.h>
//////////////////////////////////////////////////////////////////////////////
@@ -125,6 +126,14 @@ namespace basegfx
// in bWithBorder flag. It is assumed that the orientations of the given polygon are correct.
BASEGFX_DLLPUBLIC bool isInside(const B3DPolyPolygon& rCandidate, const B3DPoint& rPoint, bool bWithBorder = false);
+ /// converters for com::sun::star::drawing::PolyPolygonShape3D
+ BASEGFX_DLLPUBLIC B3DPolyPolygon UnoPolyPolygonShape3DToB3DPolyPolygon(
+ const com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DSource,
+ bool bCheckClosed = true);
+ BASEGFX_DLLPUBLIC void B3DPolyPolygonToUnoPolyPolygonShape3D(
+ const B3DPolyPolygon& rPolyPolygonSource,
+ com::sun::star::drawing::PolyPolygonShape3D& rPolyPolygonShape3DRetval);
+
} // end of namespace tools
} // end of namespace basegfx
diff --git a/sd/source/core/CustomAnimationEffect.cxx b/sd/source/core/CustomAnimationEffect.cxx
index 86cbdb68be34..0d32e356471a 100644
--- a/sd/source/core/CustomAnimationEffect.cxx
+++ b/sd/source/core/CustomAnimationEffect.cxx
@@ -1688,7 +1688,7 @@ SdrPathObj* CustomAnimationEffect::createSdrPathObjFromPath()
void CustomAnimationEffect::updateSdrPathObjFromPath( SdrPathObj& rPathObj )
{
::basegfx::B2DPolyPolygon xPolyPoly;
- if( ::basegfx::tools::importFromSvgD( xPolyPoly, getPath() ) )
+ if( ::basegfx::tools::importFromSvgD( xPolyPoly, getPath(), true, 0 ) )
{
SdrObject* pObj = GetSdrObjectFromXShape( getTargetShape() );
if( pObj )
@@ -1744,7 +1744,7 @@ void CustomAnimationEffect::updatePathFromSdrPathObj( const SdrPathObj& rPathObj
}
}
- setPath( ::basegfx::tools::exportToSvgD( xPolyPoly ) );
+ setPath( ::basegfx::tools::exportToSvgD( xPolyPoly, true, true, true) );
}
// ====================================================================
diff --git a/sdext/source/pdfimport/test/tests.cxx b/sdext/source/pdfimport/test/tests.cxx
index 5ea11848dc3e..4dc70a015489 100644
--- a/sdext/source/pdfimport/test/tests.cxx
+++ b/sdext/source/pdfimport/test/tests.cxx
@@ -236,7 +236,7 @@ namespace
const char* sExportString = "m53570 7650-35430 24100";
CPPUNIT_ASSERT_MESSAGE( "Stroke is m535.7 518.5-354.3-241",
- basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
+ basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0 );
m_bGreenStrokeSeen = true;
}
@@ -259,7 +259,7 @@ namespace
const char* sExportString = "m49890 5670.00000000001-35430 24090";
CPPUNIT_ASSERT_MESSAGE( "Stroke is m49890 5670.00000000001-35430 24090",
- basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
+ basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0 );
m_bDashedLineSeen = true;
}
@@ -317,7 +317,7 @@ namespace
const char* sExportString = "m12050 49610c-4310 0-7800-3490-7800-7800 0-4300 "
"3490-7790 7800-7790 4300 0 7790 3490 7790 7790 0 4310-3490 7800-7790 7800z";
CPPUNIT_ASSERT_MESSAGE( "Stroke is a 4-bezier circle",
- basegfx::tools::exportToSvgD( aPath ).compareToAscii(sExportString) == 0 );
+ basegfx::tools::exportToSvgD( aPath, true, true, false ).compareToAscii(sExportString) == 0 );
m_bRedCircleSeen = true;
}
diff --git a/sdext/source/pdfimport/tree/drawtreevisiting.cxx b/sdext/source/pdfimport/tree/drawtreevisiting.cxx
index a4d166e8e4df..1b3cfadd43a9 100644
--- a/sdext/source/pdfimport/tree/drawtreevisiting.cxx
+++ b/sdext/source/pdfimport/tree/drawtreevisiting.cxx
@@ -335,7 +335,7 @@ void DrawXmlEmitter::visit( PolyPolyElement& elem, const std::list< Element* >::
aBuf.append( sal_Unicode(' ') );
aBuf.append( convPx2mmPrec2(elem.h)*100.0 );
aProps[ "svg:viewBox" ] = aBuf.makeStringAndClear();
- aProps[ "svg:d" ] = basegfx::tools::exportToSvgD( elem.PolyPoly );
+ aProps[ "svg:d" ] = basegfx::tools::exportToSvgD( elem.PolyPoly, true, true, false );
m_rEmitContext.rEmitter.beginTag( "draw:path", aProps );
m_rEmitContext.rEmitter.endTag( "draw:path" );
diff --git a/sdext/source/pdfimport/tree/writertreevisiting.cxx b/sdext/source/pdfimport/tree/writertreevisiting.cxx
index 04238149efe7..6b4681e33ddc 100644
--- a/sdext/source/pdfimport/tree/writertreevisiting.cxx
+++ b/sdext/source/pdfimport/tree/writertreevisiting.cxx
@@ -275,7 +275,7 @@ void WriterXmlEmitter::visit( PolyPolyElement& elem, const std::list< Element* >
aBuf.append( sal_Unicode(' ') );
aBuf.append( convPx2mmPrec2(elem.h)*100.0 );
aProps[ "svg:viewBox" ] = aBuf.makeStringAndClear();
- aProps[ "svg:d" ] = basegfx::tools::exportToSvgD( elem.PolyPoly );
+ aProps[ "svg:d" ] = basegfx::tools::exportToSvgD( elem.PolyPoly, true, true, false );
m_rEmitContext.rEmitter.beginTag( "draw:path", aProps );
m_rEmitContext.rEmitter.endTag( "draw:path" );
diff --git a/slideshow/source/engine/animationfactory.cxx b/slideshow/source/engine/animationfactory.cxx
index 8f443059e3b1..d7877828e4fa 100644
--- a/slideshow/source/engine/animationfactory.cxx
+++ b/slideshow/source/engine/animationfactory.cxx
@@ -228,7 +228,7 @@ namespace slideshow
::basegfx::B2DPolyPolygon aPolyPoly;
- ENSURE_OR_THROW( ::basegfx::tools::importFromSvgD( aPolyPoly, rSVGDPath ),
+ ENSURE_OR_THROW( ::basegfx::tools::importFromSvgD( aPolyPoly, rSVGDPath, false, 0 ),
"PathAnimation::PathAnimation(): failed to parse SVG:d path" );
ENSURE_OR_THROW( aPolyPoly.count() == 1,
"PathAnimation::PathAnimation(): motion path consists of multiple/zero polygon(s)" );
diff --git a/svgio/inc/svgio/svgreader/svgpathnode.hxx b/svgio/inc/svgio/svgreader/svgpathnode.hxx
index a9e61d3361f4..1907baba8411 100644
--- a/svgio/inc/svgio/svgreader/svgpathnode.hxx
+++ b/svgio/inc/svgio/svgreader/svgpathnode.hxx
@@ -22,6 +22,7 @@
#include <svgio/svgreader/svgnode.hxx>
#include <svgio/svgreader/svgstyleattributes.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -33,12 +34,13 @@ namespace svgio
{
private:
/// use styles
- SvgStyleAttributes maSvgStyleAttributes;
+ SvgStyleAttributes maSvgStyleAttributes;
/// variable scan values, dependent of given XAttributeList
- basegfx::B2DPolyPolygon* mpPolyPolygon;
- basegfx::B2DHomMatrix* mpaTransform;
- SvgNumber maPathLength;
+ basegfx::B2DPolyPolygon* mpPolyPolygon;
+ basegfx::B2DHomMatrix* mpaTransform;
+ SvgNumber maPathLength;
+ basegfx::tools::PointIndexSet maHelpPointIndices;
public:
SvgPathNode(
diff --git a/svgio/inc/svgio/svgreader/svgstyleattributes.hxx b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
index be8ddd4e64e1..1624b37aebc8 100644
--- a/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
+++ b/svgio/inc/svgio/svgreader/svgstyleattributes.hxx
@@ -23,6 +23,7 @@
#include <svgio/svgreader/svgpaint.hxx>
#include <svgio/svgreader/svgnode.hxx>
#include <vcl/vclenum.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
//////////////////////////////////////////////////////////////////////////////
// predefines
@@ -250,7 +251,8 @@ namespace svgio
const SvgMarkerNode& rMarker) const;
void add_markers(
const basegfx::B2DPolyPolygon& rPath,
- drawinglayer::primitive2d::Primitive2DSequence& rTarget) const;
+ drawinglayer::primitive2d::Primitive2DSequence& rTarget,
+ const basegfx::tools::PointIndexSet* pHelpPointIndices) const;
public:
/// local attribute scanner
@@ -262,7 +264,8 @@ namespace svgio
drawinglayer::primitive2d::Primitive2DSequence& rSource) const;
void add_path(
const basegfx::B2DPolyPolygon& rPath,
- drawinglayer::primitive2d::Primitive2DSequence& rTarget) const;
+ drawinglayer::primitive2d::Primitive2DSequence& rTarget,
+ const basegfx::tools::PointIndexSet* pHelpPointIndices) const;
void add_postProcess(
drawinglayer::primitive2d::Primitive2DSequence& rTarget,
const drawinglayer::primitive2d::Primitive2DSequence& rSource,
diff --git a/svgio/source/svgreader/svgcirclenode.cxx b/svgio/source/svgreader/svgcirclenode.cxx
index c742a41f9989..f462a07e3284 100644
--- a/svgio/source/svgreader/svgcirclenode.cxx
+++ b/svgio/source/svgreader/svgcirclenode.cxx
@@ -135,7 +135,7 @@ namespace svgio
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget);
+ pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget, 0);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svgellipsenode.cxx b/svgio/source/svgreader/svgellipsenode.cxx
index aa42d7adc757..283e9da9826b 100644
--- a/svgio/source/svgreader/svgellipsenode.cxx
+++ b/svgio/source/svgreader/svgellipsenode.cxx
@@ -150,7 +150,7 @@ namespace svgio
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget);
+ pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget, 0);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svglinenode.cxx b/svgio/source/svgreader/svglinenode.cxx
index 74e9facbf973..aebefe7fdd9c 100644
--- a/svgio/source/svgreader/svglinenode.cxx
+++ b/svgio/source/svgreader/svglinenode.cxx
@@ -146,7 +146,7 @@ namespace svgio
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget);
+ pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget, 0);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svgpathnode.cxx b/svgio/source/svgreader/svgpathnode.cxx
index 9e77f723a6df..e745711e786d 100644
--- a/svgio/source/svgreader/svgpathnode.cxx
+++ b/svgio/source/svgreader/svgpathnode.cxx
@@ -69,7 +69,7 @@ namespace svgio
{
basegfx::B2DPolyPolygon aPath;
- if(basegfx::tools::importFromSvgD(aPath, aContent))
+ if(basegfx::tools::importFromSvgD(aPath, aContent, false, &maHelpPointIndices))
{
if(aPath.count())
{
@@ -114,7 +114,7 @@ namespace svgio
{
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(*getPath(), aNewTarget);
+ pStyle->add_path(*getPath(), aNewTarget, &maHelpPointIndices);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svgpolynode.cxx b/svgio/source/svgreader/svgpolynode.cxx
index eef4808404dc..c475c79f7206 100644
--- a/svgio/source/svgreader/svgpolynode.cxx
+++ b/svgio/source/svgreader/svgpolynode.cxx
@@ -20,6 +20,7 @@
#include <svgio/svgreader/svgpolynode.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
//////////////////////////////////////////////////////////////////////////////
@@ -111,7 +112,7 @@ namespace svgio
{
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(basegfx::B2DPolyPolygon(*getPolygon()), aNewTarget);
+ pStyle->add_path(basegfx::B2DPolyPolygon(*getPolygon()), aNewTarget, 0);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svgrectnode.cxx b/svgio/source/svgreader/svgrectnode.cxx
index 5d518a46c245..8348ed76ae14 100644
--- a/svgio/source/svgreader/svgrectnode.cxx
+++ b/svgio/source/svgreader/svgrectnode.cxx
@@ -207,7 +207,7 @@ namespace svgio
drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
- pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget);
+ pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget, 0);
if(aNewTarget.hasElements())
{
diff --git a/svgio/source/svgreader/svgstyleattributes.cxx b/svgio/source/svgreader/svgstyleattributes.cxx
index 958debdfe21c..0e8be846a6fc 100644
--- a/svgio/source/svgreader/svgstyleattributes.cxx
+++ b/svgio/source/svgreader/svgstyleattributes.cxx
@@ -829,7 +829,8 @@ namespace svgio
void SvgStyleAttributes::add_markers(
const basegfx::B2DPolyPolygon& rPath,
- drawinglayer::primitive2d::Primitive2DSequence& rTarget) const
+ drawinglayer::primitive2d::Primitive2DSequence& rTarget,
+ const basegfx::tools::PointIndexSet* pHelpPointIndices) const
{
// try to access linked markers
const SvgMarkerNode* pStart = accessMarkerStartXLink();
@@ -888,6 +889,18 @@ namespace svgio
pNeeded = pMid;
}
+ if(pHelpPointIndices && !pHelpPointIndices->empty())
+ {
+ const basegfx::tools::PointIndexSet::const_iterator aFound(
+ pHelpPointIndices->find(basegfx::tools::PointIndex(a, b)));
+
+ if(aFound != pHelpPointIndices->end())
+ {
+ // this point is a pure helper point; do not create a marker for it
+ continue;
+ }
+ }
+
if(!pNeeded)
{
// no marker needs to be created for this point
@@ -999,7 +1012,8 @@ namespace svgio
void SvgStyleAttributes::add_path(
const basegfx::B2DPolyPolygon& rPath,
- drawinglayer::primitive2d::Primitive2DSequence& rTarget) const
+ drawinglayer::primitive2d::Primitive2DSequence& rTarget,
+ const basegfx::tools::PointIndexSet* pHelpPointIndices) const
{
if(!rPath.count())
{
@@ -1057,7 +1071,7 @@ namespace svgio
SVGTokenLine == mrOwner.getType()) // line
{
// try to add markers
- add_markers(rPath, rTarget);
+ add_markers(rPath, rTarget, pHelpPointIndices);
}
}
diff --git a/xmloff/inc/xexptran.hxx b/xmloff/inc/xexptran.hxx
index 77944533de2b..2c8112adf360 100644
--- a/xmloff/inc/xexptran.hxx
+++ b/xmloff/inc/xexptran.hxx
@@ -93,79 +93,23 @@ public:
class SdXMLImExViewBox
{
- OUString msString;
- sal_Int32 mnX;
- sal_Int32 mnY;
- sal_Int32 mnW;
- sal_Int32 mnH;
+ OUString msString;
+ double mfX;
+ double mfY;
+ double mfW;
+ double mfH;
public:
- SdXMLImExViewBox(sal_Int32 nX = 0L, sal_Int32 nY = 0L, sal_Int32 nW = 1000L, sal_Int32 nH = 1000L);
+ SdXMLImExViewBox(double fX = 0.0, double fY = 0.0, double fW = 1000.0, double fH = 1000.0);
SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv);
- sal_Int32 GetX() const { return mnX; }
- sal_Int32 GetY() const { return mnY; }
- sal_Int32 GetWidth() const { return mnW; }
- sal_Int32 GetHeight() const { return mnH; }
+ double GetX() const { return mfX; }
+ double GetY() const { return mfY; }
+ double GetWidth() const { return mfW; }
+ double GetHeight() const { return mfH; }
const OUString& GetExportString();
};
-class SdXMLImExPointsElement
-{
- OUString msString;
- com::sun::star::drawing::PointSequenceSequence maPoly;
-
-public:
- SdXMLImExPointsElement(com::sun::star::drawing::PointSequence* pPoints,
- const SdXMLImExViewBox& rViewBox,
- const com::sun::star::awt::Point& rObjectPos,
- const com::sun::star::awt::Size& rObjectSize,
- // #96328#
- const bool bClosed = true);
- SdXMLImExPointsElement(const OUString& rNew,
- const SdXMLImExViewBox& rViewBox,
- const com::sun::star::awt::Point& rObjectPos,
- const com::sun::star::awt::Size& rObjectSize,
- const SvXMLUnitConverter& rConv);
-
- const OUString& GetExportString() const { return msString; }
- const com::sun::star::drawing::PointSequenceSequence& GetPointSequenceSequence() const { return maPoly; }
-};
-
-class SdXMLImExSvgDElement
-{
- OUString msString;
- const SdXMLImExViewBox& mrViewBox;
- bool mbIsClosed;
- bool mbIsCurve;
- bool mbRelative;
- sal_Int32 mnLastX;
- sal_Int32 mnLastY;
-
- com::sun::star::drawing::PolyPolygonBezierCoords maPoly;
-
-public:
- SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox, const SvXMLExport& rExport);
- SdXMLImExSvgDElement(const OUString& rNew,
- const SdXMLImExViewBox& rViewBox,
- const com::sun::star::awt::Point& rObjectPos,
- const com::sun::star::awt::Size& rObjectSize,
- const SvXMLImport& rImport);
-
- void AddPolygon(
- com::sun::star::drawing::PointSequence* pPoints,
- com::sun::star::drawing::FlagSequence* pFlags,
- const com::sun::star::awt::Point& rObjectPos,
- const com::sun::star::awt::Size& rObjectSize,
- bool bClosed = false);
-
- const 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.Coordinates; }
- const com::sun::star::drawing::FlagSequenceSequence& GetFlagSequenceSequence() const { return maPoly.Flags; }
-};
-
-#endif // INCLUDED_XMLOFF_INC_XEXPTRAN_HXX
+#endif // _XEXPTRANSFORM_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/XMLImageMapContext.cxx b/xmloff/source/draw/XMLImageMapContext.cxx
index efa3b48c18ab..4601b0065108 100644
--- a/xmloff/source/draw/XMLImageMapContext.cxx
+++ b/xmloff/source/draw/XMLImageMapContext.cxx
@@ -26,7 +26,6 @@
#include <com/sun/star/container/XIndexContainer.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
-
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <xmloff/xmltoken.hxx>
@@ -40,7 +39,8 @@
#include <xmloff/XMLEventsImportContext.hxx>
#include "XMLStringBufferImportContext.hxx"
#include <tools/debug.hxx>
-
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
using namespace ::com::sun::star;
using namespace ::xmloff::token;
@@ -492,34 +492,31 @@ void XMLImageMapPolygonContext::ProcessAttribute(
bValid = bViewBoxOK && bPointsOK;
}
-void XMLImageMapPolygonContext::Prepare(
- Reference<XPropertySet> & rPropertySet)
+void XMLImageMapPolygonContext::Prepare(Reference<XPropertySet> & rPropertySet)
{
// process view box
- SdXMLImExViewBox aViewBox(sViewBoxString,
- GetImport().GetMM100UnitConverter());
+ SdXMLImExViewBox aViewBox(sViewBoxString, GetImport().GetMM100UnitConverter());
// get polygon sequence
- awt::Point aPoint(aViewBox.GetX(), aViewBox.GetY());
- awt::Size aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
- SdXMLImExPointsElement aPoints( sPointsString, aViewBox, aPoint, aSize,
- GetImport().GetMM100UnitConverter() );
- PointSequenceSequence aPointSeqSeq = aPoints.GetPointSequenceSequence();
-
- // only use first element of sequence-sequence
- if (aPointSeqSeq.getLength() > 0)
+ basegfx::B2DPolygon aPolygon;
+
+ if(basegfx::tools::importFromSvgPoints(aPolygon, sPointsString))
{
- Any aAny;
- aAny <<= aPointSeqSeq[0];
- rPropertySet->setPropertyValue(sPolygon, aAny);
+ if(aPolygon.count())
+ {
+ com::sun::star::drawing::PointSequence aPointSequence;
+ uno::Any aAny;
+
+ basegfx::tools::B2DPolygonToUnoPointSequence(aPolygon, aPointSequence);
+ aAny <<= aPointSequence;
+ rPropertySet->setPropertyValue(sPolygon, aAny);
+ }
}
// parent properties
XMLImageMapObjectContext::Prepare(rPropertySet);
}
-
-
class XMLImageMapCircleContext : public XMLImageMapObjectContext
{
awt::Point aCenter;
diff --git a/xmloff/source/draw/XMLImageMapExport.cxx b/xmloff/source/draw/XMLImageMapExport.cxx
index c6e40115597a..2abba024f112 100644
--- a/xmloff/source/draw/XMLImageMapExport.cxx
+++ b/xmloff/source/draw/XMLImageMapExport.cxx
@@ -26,7 +26,6 @@
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/container/XIndexContainer.hpp>
-
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/awt/Point.hpp>
@@ -38,8 +37,8 @@
#include <xmloff/XMLEventExport.hxx>
#include <xmloff/xmluconv.hxx>
#include "xexptran.hxx"
-
-
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
using namespace ::com::sun::star;
using namespace ::xmloff::token;
@@ -314,8 +313,7 @@ void XMLImageMapExport::ExportCircle(
aBuffer.makeStringAndClear() );
}
-void XMLImageMapExport::ExportPolygon(
- const Reference<XPropertySet> & rPropertySet)
+void XMLImageMapExport::ExportPolygon(const Reference<XPropertySet> & rPropertySet)
{
// polygons get exported as bounding box, viewbox, and coordinate
// pair sequence. The bounding box is always the entire image.
@@ -325,52 +323,33 @@ void XMLImageMapExport::ExportPolygon(
PointSequence aPoly;
aAny >>= aPoly;
- // get bounding box (assume top-left to be 0,0)
- sal_Int32 nWidth = 0;
- sal_Int32 nHeight = 0;
- sal_Int32 nLength = aPoly.getLength();
- const struct awt::Point* pPointPtr = aPoly.getConstArray();
- for ( sal_Int32 i = 0; i < nLength; i++ )
- {
- sal_Int32 nPolyX = pPointPtr->X;
- sal_Int32 nPolyY = pPointPtr->Y;
-
- if ( nPolyX > nWidth )
- nWidth = nPolyX;
- if ( nPolyY > nHeight )
- nHeight = nPolyY;
-
- pPointPtr++;
- }
- DBG_ASSERT(nWidth > 0, "impossible Polygon found");
- DBG_ASSERT(nHeight > 0, "impossible Polygon found");
+ const basegfx::B2DPolygon aPolygon(
+ basegfx::tools::UnoPointSequenceToB2DPolygon(
+ aPoly));
+ const basegfx::B2DRange aPolygonRange(aPolygon.getB2DRange());
// parameters svg:x, svg:y, svg:width, svg:height
OUStringBuffer aBuffer;
+
mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, 0);
- mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X,
- aBuffer.makeStringAndClear() );
+ mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_X, aBuffer.makeStringAndClear() );
mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, 0);
- mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y,
- aBuffer.makeStringAndClear() );
- mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, nWidth);
- mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
- aBuffer.makeStringAndClear() );
- mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, nHeight);
- mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
- aBuffer.makeStringAndClear() );
+ mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_Y, aBuffer.makeStringAndClear() );
+ mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, basegfx::fround(aPolygonRange.getWidth()));
+ mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, aBuffer.makeStringAndClear() );
+ mrExport.GetMM100UnitConverter().convertMeasureToXML(aBuffer, basegfx::fround(aPolygonRange.getHeight()));
+ mrExport.AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, aBuffer.makeStringAndClear() );
// svg:viewbox
- SdXMLImExViewBox aViewBox(0, 0, nWidth, nHeight);
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
- aViewBox.GetExportString());
+ SdXMLImExViewBox aViewBox(0.0, 0.0, aPolygonRange.getWidth(), aPolygonRange.getHeight());
+ mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
// export point sequence
- awt::Point aPoint(0, 0);
- awt::Size aSize(nWidth, nHeight);
- SdXMLImExPointsElement aPoints( &aPoly, aViewBox, aPoint, aSize );
- mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_POINTS,
- aPoints.GetExportString());
+ const OUString aPointString(
+ basegfx::tools::exportToSvgPoints(
+ aPolygon));
+
+ mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/shapeexport.cxx b/xmloff/source/draw/shapeexport.cxx
index 16f5d173b282..3a2a636027e1 100644
--- a/xmloff/source/draw/shapeexport.cxx
+++ b/xmloff/source/draw/shapeexport.cxx
@@ -20,6 +20,14 @@
#include <memory>
#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/matrix/b3dhommatrix.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygon.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b3dvector.hxx>
@@ -2119,8 +2127,6 @@ void XMLShapeExport::ImpExportPolygonShape(
const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
if(xPropSet.is())
{
- sal_Bool bClosed(eShapeType == XmlShapeTypeDrawPolyPolygonShape
- || eShapeType == XmlShapeTypeDrawClosedBezierShape);
sal_Bool bBezier(eShapeType == XmlShapeTypeDrawClosedBezierShape
|| eShapeType == XmlShapeTypeDrawOpenBezierShape);
@@ -2150,111 +2156,83 @@ void XMLShapeExport::ImpExportPolygonShape(
{
// get PolygonBezier
uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
- drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
- (drawing::PolyPolygonBezierCoords*)aAny.getValue();
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*(drawing::PolyPolygonBezierCoords*)aAny.getValue()));
- if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
+ if(aPolyPolygon.count())
{
- sal_Int32 nOuterCnt(pSourcePolyPolygon->Coordinates.getLength());
- drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray();
- drawing::FlagSequence* pOuterFlags = pSourcePolyPolygon->Flags.getArray();
+ // complex polygon shape, write as svg:d
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
- if(pOuterSequence && pOuterFlags)
- {
- // prepare svx:d element export
- SdXMLImExSvgDElement aSvgDElement(aViewBox, GetExport());
-
- for(sal_Int32 a(0L); a < nOuterCnt; a++)
- {
- drawing::PointSequence* pSequence = pOuterSequence++;
- drawing::FlagSequence* pFlags = pOuterFlags++;
-
- if(pSequence && pFlags)
- {
- aSvgDElement.AddPolygon(pSequence, pFlags,
- aPoint, aSize, bClosed);
- }
- }
-
- // write point array
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
- }
+ // write point array
+ mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
// write object now
- SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PATH, bCreateNewline, sal_True);
+ SvXMLElementExport aOBJ(
+ mrExport,
+ XML_NAMESPACE_DRAW,
+ XML_PATH,
+ bCreateNewline,
+ sal_True);
- ImpExportDescription( xShape ); // #i68101#
- ImpExportEvents( xShape );
- ImpExportGluePoints( xShape );
- ImpExportText( xShape );
}
}
else
{
// get non-bezier polygon
uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
- drawing::PointSequenceSequence* pSourcePolyPolygon = (drawing::PointSequenceSequence*)aAny.getValue();
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::UnoPointSequenceSequenceToB2DPolyPolygon(*(drawing::PointSequenceSequence*)aAny.getValue()));
- if(pSourcePolyPolygon && pSourcePolyPolygon->getLength())
+ if(!aPolyPolygon.areControlPointsUsed() && 1 == aPolyPolygon.count())
{
- sal_Int32 nOuterCnt(pSourcePolyPolygon->getLength());
-
- if(1L == nOuterCnt && !bBezier)
- {
- // simple polygon shape, can be written as svg:points sequence
- drawing::PointSequence* pSequence = pSourcePolyPolygon->getArray();
- if(pSequence)
- {
- SdXMLImExPointsElement aPoints(pSequence, aViewBox, aPoint, aSize,
- // #96328#
- bClosed);
-
- // write point array
- mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPoints.GetExportString());
- }
-
- // write object now
- SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW,
- bClosed ? XML_POLYGON : XML_POLYLINE , bCreateNewline, sal_True);
-
- ImpExportDescription( xShape ); // #i68101#
- ImpExportEvents( xShape );
- ImpExportGluePoints( xShape );
- ImpExportText( xShape );
- }
- else
- {
- // polypolygon or bezier, needs to be written as a svg:path sequence
- drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->getArray();
- if(pOuterSequence)
- {
- // prepare svx:d element export
- SdXMLImExSvgDElement aSvgDElement(aViewBox, GetExport());
+ // simple polygon shape, can be written as svg:points sequence
+ const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(0));
+ const OUString aPointString(basegfx::tools::exportToSvgPoints(aPolygon));
- for(sal_Int32 a(0L); a < nOuterCnt; a++)
- {
- drawing::PointSequence* pSequence = pOuterSequence++;
- if(pSequence)
- {
- aSvgDElement.AddPolygon(pSequence, 0L, aPoint,
- aSize, bClosed);
- }
- }
+ // write point array
+ mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
- // write point array
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
- }
+ // write object now
+ SvXMLElementExport aOBJ(
+ mrExport,
+ XML_NAMESPACE_DRAW,
+ aPolygon.isClosed() ? XML_POLYGON : XML_POLYLINE,
+ bCreateNewline,
+ sal_True);
+ }
+ else
+ {
+ // complex polygon shape, write as svg:d
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
- // write object now
- SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PATH, bCreateNewline, sal_True);
+ // write point array
+ mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
- ImpExportDescription( xShape ); // #i68101#
- ImpExportEvents( xShape );
- ImpExportGluePoints( xShape );
- ImpExportText( xShape );
- }
+ // write object now
+ SvXMLElementExport aOBJ(
+ mrExport,
+ XML_NAMESPACE_DRAW,
+ XML_PATH,
+ bCreateNewline,
+ sal_True);
}
}
+
+ ImpExportDescription( xShape ); // #i68101#
+ ImpExportEvents( xShape );
+ ImpExportGluePoints( xShape );
+ ImpExportText( xShape );
}
}
@@ -2595,38 +2573,19 @@ void XMLShapeExport::ImpExportConnectorShape(
if( xProps->getPropertyValue("PolyPolygonBezier") >>= aAny )
{
// get PolygonBezier
- drawing::PolyPolygonBezierCoords* pSourcePolyPolygon =
- (drawing::PolyPolygonBezierCoords*)aAny.getValue();
+ drawing::PolyPolygonBezierCoords* pSourcePolyPolygon = (drawing::PolyPolygonBezierCoords*)aAny.getValue();
if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
{
- sal_Int32 nOuterCnt(pSourcePolyPolygon->Coordinates.getLength());
- drawing::PointSequence* pOuterSequence = pSourcePolyPolygon->Coordinates.getArray();
- drawing::FlagSequence* pOuterFlags = pSourcePolyPolygon->Flags.getArray();
-
- if(pOuterSequence && pOuterFlags)
- {
- // prepare svx:d element export
- awt::Point aPoint( 0, 0 );
- awt::Size aSize( 1, 1 );
- SdXMLImExViewBox aViewBox( 0, 0, 1, 1 );
- SdXMLImExSvgDElement aSvgDElement(aViewBox, GetExport());
-
- for(sal_Int32 a(0L); a < nOuterCnt; a++)
- {
- drawing::PointSequence* pSequence = pOuterSequence++;
- drawing::FlagSequence* pFlags = pOuterFlags++;
-
- if(pSequence && pFlags)
- {
- aSvgDElement.AddPolygon(pSequence, pFlags,
- aPoint, aSize, sal_False );
- }
- }
-
- // write point array
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
- }
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
+ *pSourcePolyPolygon));
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
}
}
@@ -3440,104 +3399,45 @@ void XMLShapeExport::ImpExport3DShape(
case XmlShapeTypeDraw3DLatheObject:
case XmlShapeTypeDraw3DExtrudeObject:
{
- // write special 3DLathe/3DExtrude attributes
+ // write special 3DLathe/3DExtrude attributes, get 3D PolyPolygon as drawing::PolyPolygonShape3D
aAny = xPropSet->getPropertyValue("D3DPolyPolygon3D");
drawing::PolyPolygonShape3D xPolyPolygon3D;
aAny >>= xPolyPolygon3D;
- // look for maximal values
- double fXMin = 0;
- double fXMax = 0;
- double fYMin = 0;
- double fYMax = 0;
- sal_Bool bInit(sal_False);
- sal_Int32 nOuterSequenceCount(xPolyPolygon3D.SequenceX.getLength());
- drawing::DoubleSequence* pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
- drawing::DoubleSequence* pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
-
- sal_Int32 a;
- for (a = 0; a < nOuterSequenceCount; a++)
- {
- sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
- double* pArrayX = pInnerSequenceX->getArray();
- double* pArrayY = pInnerSequenceY->getArray();
-
- for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
- {
- double fX = *pArrayX++;
- double fY = *pArrayY++;
+ // convert to 3D PolyPolygon
+ const basegfx::B3DPolyPolygon aPolyPolygon3D(
+ basegfx::tools::UnoPolyPolygonShape3DToB3DPolyPolygon(
+ xPolyPolygon3D));
- if(bInit)
- {
- if(fX > fXMax)
- fXMax = fX;
+ // convert to 2D PolyPolygon using identity 3D transformation (just grep X and Y)
+ const basegfx::B3DHomMatrix aB3DHomMatrixFor2DConversion;
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(
+ aPolyPolygon3D,
+ aB3DHomMatrixFor2DConversion));
- if(fX < fXMin)
- fXMin = fX;
-
- if(fY > fYMax)
- fYMax = fY;
-
- if(fY < fYMin)
- fYMin = fY;
- }
- else
- {
- fXMin = fXMax = fX;
- fYMin = fYMax = fY;
- bInit = sal_True;
- }
- }
-
- pInnerSequenceX++;
- pInnerSequenceY++;
- }
+ // get 2D range of it
+ const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
// export ViewBox
- awt::Point aMinPoint(FRound(fXMin), FRound(fYMin));
- awt::Size aMaxSize(FRound(fXMax) - aMinPoint.X, FRound(fYMax) - aMinPoint.Y);
SdXMLImExViewBox aViewBox(
- aMinPoint.X, aMinPoint.Y, aMaxSize.Width, aMaxSize.Height);
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
- aViewBox.GetExportString());
+ aPolyPolygonRange.getMinX(),
+ aPolyPolygonRange.getMinY(),
+ aPolyPolygonRange.getWidth(),
+ aPolyPolygonRange.getHeight());
- // prepare svx:d element export
- SdXMLImExSvgDElement aSvgDElement(aViewBox, GetExport());
- pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
- pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
+ mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
- for (a = 0; a < nOuterSequenceCount; a++)
- {
- sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
- double* pArrayX = pInnerSequenceX->getArray();
- double* pArrayY = pInnerSequenceY->getArray();
- drawing::PointSequence aPoly(nInnerSequenceCount);
- awt::Point* pInnerSequence = aPoly.getArray();
-
- for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
- {
- double fX = *pArrayX++;
- double fY = *pArrayY++;
-
- *pInnerSequence = awt::Point(FRound(fX), FRound(fY));
- pInnerSequence++;
- }
-
- // calculate closed flag
- awt::Point* pFirst = aPoly.getArray();
- awt::Point* pLast = pFirst + (nInnerSequenceCount - 1);
- sal_Bool bClosed = (pFirst->X == pLast->X && pFirst->Y == pLast->Y);
-
- aSvgDElement.AddPolygon(&aPoly, 0L, aMinPoint,
- aMaxSize, bClosed);
-
- // #80594# corrected error in PolyPolygon3D export for 3D XML
- pInnerSequenceX++;
- pInnerSequenceY++;
- }
+ // prepare svg:d string
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers TTTT: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
// write point array
- mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
+ mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
if(eShapeType == XmlShapeTypeDraw3DLatheObject)
{
diff --git a/xmloff/source/draw/xexptran.cxx b/xmloff/source/draw/xexptran.cxx
index 5f131251f6ee..dbc5cdbe9c4d 100644
--- a/xmloff/source/draw/xexptran.cxx
+++ b/xmloff/source/draw/xexptran.cxx
@@ -245,6 +245,13 @@ double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32
return fRetval;
}
+void Imp_PutDoubleChar(OUString& rStr, double fValue)
+{
+ OUStringBuffer sStringBuffer;
+ ::sax::Converter::convertDouble(sStringBuffer, fValue);
+ rStr += OUString(sStringBuffer.makeStringAndClear());
+}
+
void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
bool bConvertUnits = false)
{
@@ -1206,21 +1213,21 @@ void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
}
}
-SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH)
-: mnX( nX ),
- mnY( nY ),
- mnW( nW ),
- mnH( nH )
+SdXMLImExViewBox::SdXMLImExViewBox(double fX, double fY, double fW, double fH)
+: mfX( fX ),
+ mfY( fY ),
+ mfW( fW ),
+ mfH( fH )
{
}
// #100617# Asked vincent hardy: svg:viewBox values may be double precision.
SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
: msString(rNew),
- mnX( 0L ),
- mnY( 0L ),
- mnW( 1000L ),
- mnH( 1000L )
+ mfX( 0.0 ),
+ mfY( 0.0 ),
+ mfW( 1000.0 ),
+ mfH( 1000.0 )
{
if(!msString.isEmpty())
{
@@ -1232,25 +1239,25 @@ SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverte
Imp_SkipSpaces(aStr, nPos, nLen);
// get mX, #100617# be prepared for doubles
- mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX));
+ mfX = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfX);
// skip spaces and commas
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// get mY, #100617# be prepared for doubles
- mnY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnY));
+ mfY = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfY);
// skip spaces and commas
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// get mW, #100617# be prepared for doubles
- mnW = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnW));
+ mfW = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfW);
// skip spaces and commas
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// get mH, #100617# be prepared for doubles
- mnH = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnH));
+ mfH = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfH);
}
}
@@ -1259,16 +1266,16 @@ const OUString& SdXMLImExViewBox::GetExportString()
OUString aNewString;
OUString aEmptySpace(" ");
- Imp_PutNumberChar(aNewString, mnX);
+ Imp_PutDoubleChar(aNewString, mfX);
aNewString += aEmptySpace;
- Imp_PutNumberChar(aNewString, mnY);
+ Imp_PutDoubleChar(aNewString, mfY);
aNewString += aEmptySpace;
- Imp_PutNumberChar(aNewString, mnW);
+ Imp_PutDoubleChar(aNewString, mfW);
aNewString += aEmptySpace;
- Imp_PutNumberChar(aNewString, mnH);
+ Imp_PutDoubleChar(aNewString, mfH);
// set new string
msString = aNewString;
@@ -1276,872 +1283,4 @@ const OUString& SdXMLImExViewBox::GetExportString()
return msString;
}
-SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints,
- const SdXMLImExViewBox& rViewBox,
- const awt::Point& rObjectPos,
- const awt::Size& rObjectSize,
- // #96328#
- const bool bClosed)
-: maPoly( 0L )
-{
- DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
-
- // add polygon to string
- sal_Int32 nCnt(pPoints->getLength());
-
- // #104076# Convert to string only when at last one point included
- if(nCnt > 0)
- {
- OUString aNewString;
- awt::Point* pArray = pPoints->getArray();
-
- // last point same? Ignore it.
- // #96328# ...but only when polygon is CLOSED
- if(bClosed && (pArray->X == (pArray + (nCnt - 1))->X) && (pArray->Y == (pArray + (nCnt - 1))->Y))
- nCnt--;
-
- // object size and ViewBox size different?
- bool bScale(rObjectSize.Width != rViewBox.GetWidth()
- || rObjectSize.Height != rViewBox.GetHeight());
- bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
-
- for(sal_Int32 a(0L); a < nCnt; a++)
- {
- // prepare coordinates
- sal_Int32 nX( pArray->X - rObjectPos.X );
- sal_Int32 nY( pArray->Y - rObjectPos.Y );
-
- if(bScale && rObjectSize.Width && rObjectSize.Height)
- {
- nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width;
- nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height;
- }
-
- if(bTranslate)
- {
- nX += rViewBox.GetX();
- nY += rViewBox.GetY();
- }
-
- // X and comma
- Imp_PutNumberChar(aNewString, nX);
- aNewString += ",";
-
- // Y and space (not for last)
- Imp_PutNumberChar(aNewString, nY);
- if(a + 1 != nCnt)
- aNewString += " ";
-
- // next point
- pArray++;
- }
-
- // set new string
- msString = aNewString;
- }
-}
-
-// #100617# svg:polyline or svg:polygon values may be double precision.
-SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString& rNew,
- const SdXMLImExViewBox& rViewBox,
- const awt::Point& rObjectPos,
- const awt::Size& rObjectSize,
- const SvXMLUnitConverter& rConv)
-: msString( rNew ),
- maPoly( 0L )
-{
- // convert string to polygon
- const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
- const sal_Int32 nLen(aStr.getLength());
- sal_Int32 nPos(0);
- sal_Int32 nNumPoints(0L);
-
- // skip starting spaces
- Imp_SkipSpaces(aStr, nPos, nLen);
-
- // count points in first loop
- while(nPos < nLen)
- {
- // skip number, #100617# be prepared for doubles
- Imp_SkipDouble(aStr, nPos, nLen);
-
- // skip spaces and commas
- Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
-
- // skip number, #100617# be prepared for doubles
- Imp_SkipDouble(aStr, nPos, nLen);
-
- // skip spaces and commas
- Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
-
- // one more point
- nNumPoints++;
- }
-
- // second loop
- if(nNumPoints)
- {
- nPos = 0;
- maPoly.realloc(1);
- drawing::PointSequence* pOuterSequence = maPoly.getArray();
- pOuterSequence->realloc(nNumPoints);
- awt::Point* pInnerSequence = pOuterSequence->getArray();
-
- // object size and ViewBox size different?
- bool bScale(rObjectSize.Width != rViewBox.GetWidth()
- || rObjectSize.Height != rViewBox.GetHeight());
- bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
-
- // skip starting spaces
- Imp_SkipSpaces(aStr, nPos, nLen);
-
- while(nPos < nLen)
- {
- // prepare new parameter pair
- sal_Int32 nX(0L);
- sal_Int32 nY(0L);
-
- // get mX, #100617# be prepared for doubles
- nX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nX));
-
- // skip spaces and commas
- Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
-
- // get mY, #100617# be prepared for doubles
- nY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nY));
-
- // skip spaces and commas
- Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
-
- // prepare parameters
- 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;
-
- // add new point
- *pInnerSequence = awt::Point( nX, nY );
- pInnerSequence++;
- }
- }
-}
-
-SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox,
- const SvXMLExport& rExport)
-: mrViewBox( rViewBox ),
- mbIsClosed( false ),
- mbIsCurve( false ),
- // fdo#47406 - handle writing svg:d path slightly different for
- // old ODF versions and ODF1.2 compat mode - since ~all the legacy
- // ODF ecosystem interprets relative svg:d paths incorrectly,
- // write out absolute paths in those cases.
- mbRelative( rExport.getDefaultVersion() >= SvtSaveOptions::ODFVER_012 &&
- rExport.getDefaultVersion() != SvtSaveOptions::ODFVER_012_EXT_COMPAT ),
- mnLastX( 0L ),
- mnLastY( 0L ),
- maPoly()
-{
-}
-
-void Imp_GetPrevPos(awt::Point*& pPrevPos1,
- drawing::PolygonFlags& aPrevFlag1,
- const bool bClosed, awt::Point* pPoints,
- drawing::PolygonFlags* pFlags, const sal_Int32 nPos,
- const sal_Int32 nCnt, const sal_Int32 nAdd)
-{
- if(bClosed)
- {
- pPrevPos1 = pPoints + ((nPos + nCnt - nAdd) % nCnt);
- aPrevFlag1 = *(pFlags + ((nPos + nCnt - nAdd) % nCnt));
- }
- else if(nPos > (nAdd - 1))
- {
- pPrevPos1 = pPoints + (nPos - nAdd);
- aPrevFlag1 = *(pFlags + (nPos - nAdd));
- }
- else
- pPrevPos1 = 0L;
-}
-
-void Imp_PrepareCoorExport(sal_Int32& nX, sal_Int32& nY,
- const awt::Point* pPointArray, const awt::Point& rObjectPos,
- const awt::Size& rObjectSize, const SdXMLImExViewBox& mrViewBox,
- const bool bScale, const bool bTranslate)
-{
- nX = pPointArray->X - rObjectPos.X;
- nY = pPointArray->Y - rObjectPos.Y;
-
- if(bScale && rObjectSize.Width && rObjectSize.Height )
- {
- nX = (nX * mrViewBox.GetWidth()) / rObjectSize.Width;
- nY = (nY * mrViewBox.GetHeight()) / rObjectSize.Height;
- }
-
- if(bTranslate)
- {
- nX += mrViewBox.GetX();
- nY += mrViewBox.GetY();
- }
-}
-
-//#define TEST_QUADRATIC_CURVES
-#ifdef TEST_QUADRATIC_CURVES
-// To be able to test quadratic curve code: The code concerning to
-// bDoTestHere can be used (see below). Construct shapes which have their control
-// points on equal coordinates. When these are written, they can be
-// forced to create correct 'Q' and 'T' statements using this flag.
-// These may then be tested for import/exporting.
-static bool bDoTestHere(true);
-#endif // TEST_QUADRATIC_CURVES
-
-void SdXMLImExSvgDElement::AddPolygon(
- drawing::PointSequence* pPoints,
- drawing::FlagSequence* pFlags,
- const awt::Point& rObjectPos,
- const awt::Size& rObjectSize,
- bool bClosed)
-{
- // 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());
-
- // #104076# Convert to string only when at last one point included
- if(nCnt > 0)
- {
- // append polygon to string
- OUString aNewString;
- sal_Unicode aLastCommand = ' ';
- awt::Point* pPointArray = pPoints->getArray();
-
- // are the flags used at all? If not forget about them
- if(pFlags)
- {
- sal_Int32 nFlagCnt(pFlags->getLength());
-
- if(nFlagCnt)
- {
- bool bFlagsUsed(false);
- drawing::PolygonFlags* pFlagArray = pFlags->getArray();
-
- for(sal_Int32 a(0); !bFlagsUsed && a < nFlagCnt; a++)
- if(drawing::PolygonFlags_NORMAL != *pFlagArray++)
- bFlagsUsed = true;
-
- if(!bFlagsUsed)
- pFlags = 0L;
- }
- else
- {
- pFlags = 0L;
- }
- }
-
- // object size and ViewBox size different?
- bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
- || rObjectSize.Height != mrViewBox.GetHeight());
- bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
-
- // #87202# rework of point reduction:
- // Test for Last point same -> closed, ignore last point. Take
- // some more circumstances in account when looking at curve segments.
- drawing::PolygonFlags* pFlagArray = (pFlags) ? pFlags->getArray() : 0L;
-
- // #i121090# only reduce double start/end points if polygon *is* closed
- if(bClosed && (pPointArray->X == (pPointArray + (nCnt - 1))->X) && (pPointArray->Y == (pPointArray + (nCnt - 1))->Y))
- {
- if(pFlags)
- {
- // point needs to be ignored if point before it is
- // NO control point. Else the last point is needed
- // for exporting the last segment of the curve. That means
- // that the last and the first point will be saved double,
- // but SVG does not support a better solution here.
- if(nCnt >= 2 && drawing::PolygonFlags_CONTROL != *(pFlagArray + (nCnt - 2)))
- {
- nCnt--;
- }
- }
- else
- {
- // no curve, ignore last point
- nCnt--;
- }
- }
-
- // bezier poly, handle curves
- bool bDidWriteStart(false);
- sal_Int32 nStartX(0), nStartY(0);
-
- for(sal_Int32 a(0L); a < nCnt; a++)
- {
- if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray++)
- {
- bool bDidWriteAsCurve(false);
-
- if(bDidWriteStart)
- {
- if(pFlags)
- {
- // real curve point, get previous to see if it's a control point
- awt::Point* pPrevPos1;
- drawing::PolygonFlags aPrevFlag1;
-
- Imp_GetPrevPos(pPrevPos1, aPrevFlag1, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 1);
-
- if(pPrevPos1 && drawing::PolygonFlags_CONTROL == aPrevFlag1)
- {
- // get previous2 to see if it's a control point, too
- awt::Point* pPrevPos2;
- drawing::PolygonFlags aPrevFlag2;
-
- Imp_GetPrevPos(pPrevPos2, aPrevFlag2, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 2);
-
- if(pPrevPos2 && drawing::PolygonFlags_CONTROL == aPrevFlag2)
- {
- // get previous3 to see if it's a curve point and if,
- // if it is fully symmetric or not
- awt::Point* pPrevPos3;
- drawing::PolygonFlags aPrevFlag3;
-
- Imp_GetPrevPos(pPrevPos3, aPrevFlag3, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 3);
-
- if(pPrevPos3)
- {
- // prepare coordinates
- sal_Int32 nX, nY;
-
- Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- // #100617# test if this curve segment may be written as
- // a quadratic bezier
- // That's the case if both control points are in the same place
- // when they are prolonged to the common quadratic control point
- // Left: P = (3P1 - P0) / 2
- // Right: P = (3P2 - P3) / 2
- bool bIsQuadratic(false);
- const bool bEnableSaveQuadratic(false);
-
- sal_Int32 nPX_L(FRound((double)((3 * pPrevPos2->X) - pPrevPos3->X) / 2.0));
- sal_Int32 nPY_L(FRound((double)((3 * pPrevPos2->Y) - pPrevPos3->Y) / 2.0));
- sal_Int32 nPX_R(FRound((double)((3 * pPrevPos1->X) - pPointArray->X) / 2.0));
- sal_Int32 nPY_R(FRound((double)((3 * pPrevPos1->Y) - pPointArray->Y) / 2.0));
- sal_Int32 nDist(0);
-
- if(nPX_L != nPX_R)
- {
- nDist += abs(nPX_L - nPX_R);
- }
-
- if(nPY_L != nPY_R)
- {
- nDist += abs(nPY_L - nPY_R);
- }
-
- if(nDist <= BORDER_INTEGERS_ARE_EQUAL)
- {
- if(bEnableSaveQuadratic)
- {
- bIsQuadratic = true;
- }
- }
-
-#ifdef TEST_QUADRATIC_CURVES
- if(bDoTestHere)
- {
- bIsQuadratic = false;
-
- if(pPrevPos1->X == pPrevPos2->X && pPrevPos1->Y == pPrevPos2->Y)
- bIsQuadratic = true;
- }
-#endif // TEST_QUADRATIC_CURVES
-
- if(bIsQuadratic)
- {
-#ifdef TEST_QUADRATIC_CURVES
- if(bDoTestHere)
- {
- bool bPrevPointIsSymmetric(false);
-
- if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
- {
- // get previous4 to see if it's a control point
- awt::Point* pPrevPos4;
- drawing::PolygonFlags aPrevFlag4;
-
- Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 4);
-
- if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
- {
- // okay, prevPos3 is symmetric (c2) and prevPos4
- // is existing control point, the 's' statement can be used
- bPrevPointIsSymmetric = true;
- }
- }
-
- if(bPrevPointIsSymmetric)
- {
- // write a shorthand/smooth quadratic curveto entry (T)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('t'))
- aNewString += "t";
-
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('t');
- }
- else
- {
- if(aLastCommand != sal_Unicode('T'))
- aNewString += "T";
-
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('T');
- }
- }
- else
- {
- // prepare coordinates
- sal_Int32 nX1, nY1;
-
- Imp_PrepareCoorExport(nX1, nY1, pPrevPos1, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- // write a quadratic curveto entry (Q)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('q'))
- aNewString += "q";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('q');
- }
- else
- {
- if(aLastCommand != sal_Unicode('Q'))
- aNewString += "Q";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1);
- Imp_PutNumberCharWithSpace(aNewString, nY1);
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('Q');
- }
- }
- }
- else
- {
-#endif // TEST_QUADRATIC_CURVES
- awt::Point aNewPoint(nPX_L, nPY_L);
- bool bPrevPointIsSmooth(false);
-
- if(drawing::PolygonFlags_SMOOTH == aPrevFlag3)
- {
- // get previous4 to see if it's a control point
- awt::Point* pPrevPos4;
- drawing::PolygonFlags aPrevFlag4;
-
- Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 4);
-
- if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
- {
- // okay, prevPos3 is smooth (c1) and prevPos4
- // is existing control point. Test if it's even symmetric
- // and thus the 'T' statement may be used.
- ::basegfx::B2DVector aVec1(pPrevPos4->X - pPrevPos3->X, pPrevPos4->Y - pPrevPos3->Y);
- ::basegfx::B2DVector aVec2(aNewPoint.X - pPrevPos3->X, aNewPoint.Y - pPrevPos3->Y);
- bool bSameLength(false);
- bool bSameDirection(false);
-
- // get vector values
- Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
-
- if(bSameLength && bSameDirection)
- bPrevPointIsSmooth = true;
- }
- }
-
- if(bPrevPointIsSmooth)
- {
- // write a shorthand/smooth quadratic curveto entry (T)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('t'))
- aNewString += "t";
-
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('t');
- }
- else
- {
- if(aLastCommand != sal_Unicode('T'))
- aNewString += "T";
-
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('T');
- }
- }
- else
- {
- // prepare coordinates
- sal_Int32 nX1, nY1;
-
- Imp_PrepareCoorExport(nX1, nY1, &aNewPoint, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- // write a quadratic curveto entry (Q)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('q'))
- aNewString += "q";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('q');
- }
- else
- {
- if(aLastCommand != sal_Unicode('Q'))
- aNewString += "Q";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1);
- Imp_PutNumberCharWithSpace(aNewString, nY1);
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('Q');
- }
- }
-#ifdef TEST_QUADRATIC_CURVES
- }
-#endif // TEST_QUADRATIC_CURVES
- }
- else
- {
- bool bPrevPointIsSymmetric(false);
-
- if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
- {
- // get previous4 to see if it's a control point
- awt::Point* pPrevPos4;
- drawing::PolygonFlags aPrevFlag4;
-
- Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
- pFlags->getArray(), a, nCnt, 4);
-
- if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
- {
- // okay, prevPos3 is symmetric (c2) and prevPos4
- // is existing control point, the 's' statement can be used
- bPrevPointIsSymmetric = true;
- }
- }
-
- // prepare coordinates
- sal_Int32 nX2, nY2;
-
- Imp_PrepareCoorExport(nX2, nY2, pPrevPos1, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- if(bPrevPointIsSymmetric)
- {
- // write a shorthand/smooth curveto entry (S)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('s'))
- aNewString += "s";
-
- Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('s');
- }
- else
- {
- if(aLastCommand != sal_Unicode('S'))
- aNewString += "S";
-
- Imp_PutNumberCharWithSpace(aNewString, nX2);
- Imp_PutNumberCharWithSpace(aNewString, nY2);
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('S');
- }
- }
- else
- {
- // prepare coordinates
- sal_Int32 nX1, nY1;
-
- Imp_PrepareCoorExport(nX1, nY1, pPrevPos2, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- // write a curveto entry (C)
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('c'))
- aNewString += "c";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
- Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('c');
- }
- else
- {
- if(aLastCommand != sal_Unicode('C'))
- aNewString += "C";
-
- Imp_PutNumberCharWithSpace(aNewString, nX1);
- Imp_PutNumberCharWithSpace(aNewString, nY1);
- Imp_PutNumberCharWithSpace(aNewString, nX2);
- Imp_PutNumberCharWithSpace(aNewString, nY2);
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('C');
- }
- }
- }
-
- // remember that current point IS written
- bDidWriteAsCurve = true;
-
- // remember new last position
- mnLastX = nX;
- mnLastY = nY;
- }
- }
- }
- }
- }
-
- if(!bDidWriteAsCurve)
- {
- // current point not yet written, prepare coordinates
- sal_Int32 nX, nY;
-
- Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
- mrViewBox, bScale, bTranslate);
-
- if(bDidWriteStart)
- {
- // write as normal point
- if(mnLastX == nX)
- {
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('v'))
- aNewString += "v";
-
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('v');
- }
- else
- {
- if(aLastCommand != sal_Unicode('V'))
- aNewString += "V";
-
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('V');
- }
- }
- else if(mnLastY == nY)
- {
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('h'))
- aNewString += "h";
-
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
-
- aLastCommand = sal_Unicode('h');
- }
- else
- {
- if(aLastCommand != sal_Unicode('H'))
- aNewString += "H";
-
- Imp_PutNumberCharWithSpace(aNewString, nX);
-
- aLastCommand = sal_Unicode('H');
- }
- }
- else
- {
- if(mbRelative)
- {
- if(aLastCommand != sal_Unicode('l'))
- aNewString += "l";
-
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('l');
- }
- else
- {
- if(aLastCommand != sal_Unicode('L'))
- aNewString += "L";
-
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('L');
- }
- }
- }
- else
- {
- // write as start point
- if(mbRelative)
- {
- aNewString += "m";
-
- Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
- Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
-
- aLastCommand = sal_Unicode('l');
- }
- else
- {
- aNewString += "M";
-
- Imp_PutNumberCharWithSpace(aNewString, nX);
- Imp_PutNumberCharWithSpace(aNewString, nY);
-
- aLastCommand = sal_Unicode('L');
- }
-
- // remember start written
- bDidWriteStart = true;
- nStartX = nX;
- nStartY = nY;
- }
-
- // remember new last position
- mnLastX = nX;
- mnLastY = nY;
- }
- }
-
- // next point
- pPointArray++;
- }
-
- // close path if closed poly
- if(bClosed)
- {
- if(mbRelative)
- aNewString += "z";
- else
- aNewString += "Z";
-
- // update current point - we're back at the start
- if( bDidWriteStart )
- {
- mnLastX = nStartX;
- mnLastY = nStartY;
- }
- }
-
- // append new string
- msString += aNewString;
- }
-}
-
-SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew,
- const SdXMLImExViewBox& rViewBox,
- const awt::Point& rObjectPos,
- const awt::Size& rObjectSize,
- const SvXMLImport& rImport)
-: msString( rNew ),
- mrViewBox( rViewBox ),
- mbIsClosed( false ),
- mbIsCurve( false ),
- mbRelative( true ),
- mnLastX( 0L ),
- mnLastY( 0L ),
- maPoly()
-{
- bool bWrongPositionAfterZ( false );
- sal_Int32 nUPD( 0 );
- sal_Int32 nBuildId( 0 );
- if ( rImport.getBuildIds( nUPD, nBuildId ) &&
- ( ( nUPD == 641 ) || ( nUPD == 645 ) || ( nUPD == 680 ) || ( nUPD == 300 ) ||
- ( nUPD == 310 ) || ( nUPD == 320 ) || ( nUPD == 330 ) || ( nUPD == 340 ) ||
- ( nUPD == 350 && nBuildId < 202 ) ) )
- {
- bWrongPositionAfterZ = true;
- }
-
- // convert string to polygon
- basegfx::B2DPolyPolygon aPoly;
- basegfx::tools::importFromSvgD(aPoly,msString,bWrongPositionAfterZ);
-
- mbIsCurve = aPoly.areControlPointsUsed();
- mbIsClosed = aPoly.isClosed();
-
- // 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(
- (mrViewBox.GetWidth() ? rObjectSize.Width / mrViewBox.GetWidth() : 0),
- (mrViewBox.GetHeight() ? rObjectSize.Height / mrViewBox.GetHeight() : 0));
- aTransform.translate( rObjectPos.X, rObjectPos.Y );
- aPoly.transform(aTransform);
-
- basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier(aPoly,maPoly);
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/xmloff/source/draw/ximp3dobject.cxx b/xmloff/source/draw/ximp3dobject.cxx
index ae53e0a8a628..6992a12c2314 100644
--- a/xmloff/source/draw/ximp3dobject.cxx
+++ b/xmloff/source/draw/ximp3dobject.cxx
@@ -31,6 +31,9 @@
#include <xmloff/xmltoken.hxx>
#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
#include <com/sun/star/drawing/DoubleSequence.hpp>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b3dpolypolygontools.hxx>
using namespace ::com::sun::star;
@@ -345,60 +348,37 @@ SdXML3DPolygonBasedShapeContext::~SdXML3DPolygonBasedShapeContext()
void SdXML3DPolygonBasedShapeContext::StartElement(const uno::Reference< xml::sax::XAttributeList>& xAttrList)
{
uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
+
if(xPropSet.is())
{
// set parameters
if(!maPoints.isEmpty() && !maViewBox.isEmpty())
{
- SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
- awt::Point aMinPoint(aViewBox.GetX(), aViewBox.GetY());
- awt::Size aMaxSize(aViewBox.GetWidth(), aViewBox.GetHeight());
- SdXMLImExSvgDElement aPoints(maPoints, aViewBox, aMinPoint, aMaxSize, GetImport());
-
- // convert to double sequences
- drawing::PointSequenceSequence& xPoSeSe =
- (drawing::PointSequenceSequence&)aPoints.GetPointSequenceSequence();
- sal_Int32 nOuterSequenceCount = xPoSeSe.getLength();
- drawing::PointSequence* pInnerSequence = xPoSeSe.getArray();
-
- drawing::PolyPolygonShape3D xPolyPolygon3D;
- xPolyPolygon3D.SequenceX.realloc(nOuterSequenceCount);
- xPolyPolygon3D.SequenceY.realloc(nOuterSequenceCount);
- xPolyPolygon3D.SequenceZ.realloc(nOuterSequenceCount);
- drawing::DoubleSequence* pOuterSequenceX = xPolyPolygon3D.SequenceX.getArray();
- drawing::DoubleSequence* pOuterSequenceY = xPolyPolygon3D.SequenceY.getArray();
- drawing::DoubleSequence* pOuterSequenceZ = xPolyPolygon3D.SequenceZ.getArray();
-
- for(sal_Int32 a(0L); a < nOuterSequenceCount; a++)
- {
- sal_Int32 nInnerSequenceCount(pInnerSequence->getLength());
- awt::Point* pArray = pInnerSequence->getArray();
-
- pOuterSequenceX->realloc(nInnerSequenceCount);
- pOuterSequenceY->realloc(nInnerSequenceCount);
- pOuterSequenceZ->realloc(nInnerSequenceCount);
- double* pInnerSequenceX = pOuterSequenceX->getArray();
- double* pInnerSequenceY = pOuterSequenceY->getArray();
- double* pInnerSequenceZ = pOuterSequenceZ->getArray();
-
- for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
- {
- *pInnerSequenceX++ = pArray->X;
- *pInnerSequenceY++ = pArray->Y;
- *pInnerSequenceZ++ = 0.0;
- pArray++;
- }
- pInnerSequence++;
+ // import 2d PolyPolygon from svg:d
+ basegfx::B2DPolyPolygon aPolyPolygon;
- pOuterSequenceX++;
- pOuterSequenceY++;
- pOuterSequenceZ++;
+ if(basegfx::tools::importFromSvgD(aPolyPolygon, maPoints, true, 0))
+ {
+ // convert to 3D PolyPolygon
+ const basegfx::B3DPolyPolygon aB3DPolyPolygon(
+ basegfx::tools::createB3DPolyPolygonFromB2DPolyPolygon(
+ aPolyPolygon));
+
+ // convert to UNO API class PolyPolygonShape3D
+ drawing::PolyPolygonShape3D xPolyPolygon3D;
+ basegfx::tools::B3DPolyPolygonToUnoPolyPolygonShape3D(
+ aB3DPolyPolygon,
+ xPolyPolygon3D);
+
+ // set polygon data
+ uno::Any aAny;
+ aAny <<= xPolyPolygon3D;
+ xPropSet->setPropertyValue(OUString("D3DPolyPolygon3D"), aAny);
+ }
+ else
+ {
+ OSL_ENSURE(false, "Error on importing svg:d for 3D PolyPolygon (!)");
}
-
- // set poly
- uno::Any aAny;
- aAny <<= xPolyPolygon3D;
- xPropSet->setPropertyValue("D3DPolyPolygon3D", aAny);
}
// call parent
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index ed9def807223..fcfb945c6378 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -76,7 +76,11 @@
#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/vector/b2dvector.hxx>
using namespace ::com::sun::star;
@@ -1280,20 +1284,45 @@ void SdXMLPolygonShapeContext::StartElement(const uno::Reference< xml::sax::XAtt
// set polygon
if(!maPoints.isEmpty() && !maViewBox.isEmpty())
{
- SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
- awt::Size aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
- if (maSize.Width != 0 && maSize.Height !=0)
+ const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
+ basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
+
+ // Is this correct? It overrides ViewBox stuff; OTOH it makes no
+ // sense to have the geometry content size different from object size
+ if(maSize.Width != 0 && maSize.Height != 0)
{
- aSize = maSize;
+ aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
}
- awt::Point aPosition(aViewBox.GetX(), aViewBox.GetY());
- SdXMLImExPointsElement aPoints(maPoints, aViewBox,
- aPosition, aSize, GetImport().GetMM100UnitConverter());
- uno::Any aAny;
- aAny <<= aPoints.GetPointSequenceSequence();
- xPropSet->setPropertyValue(
- OUString("Geometry"), aAny);
+ basegfx::B2DPolygon aPolygon;
+
+ if(basegfx::tools::importFromSvgPoints(aPolygon, maPoints))
+ {
+ if(aPolygon.count())
+ {
+ const basegfx::B2DRange aSourceRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolygon.transform(
+ basegfx::tools::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
+
+ com::sun::star::drawing::PointSequenceSequence aPointSequenceSequence;
+ uno::Any aAny;
+
+ basegfx::tools::B2DPolyPolygonToUnoPointSequenceSequence(basegfx::B2DPolyPolygon(aPolygon), aPointSequenceSequence);
+ aAny <<= aPointSequenceSequence;
+ xPropSet->setPropertyValue(OUString("Geometry"), aAny);
+ }
+ }
}
}
@@ -1346,84 +1375,110 @@ void SdXMLPathShapeContext::StartElement(const uno::Reference< xml::sax::XAttrib
// create polygon shape
if(!maD.isEmpty())
{
- // prepare some of the parameters
- SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
- awt::Size aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
- awt::Point aPosition(aViewBox.GetX(), aViewBox.GetY());
- if (maSize.Width != 0 && maSize.Height !=0)
- {
- aSize = maSize;
- }
- SdXMLImExSvgDElement aPoints(maD, aViewBox, aPosition, aSize, GetImport());
+ const SdXMLImExViewBox aViewBox(maViewBox, GetImport().GetMM100UnitConverter());
+ basegfx::B2DVector aSize(aViewBox.GetWidth(), aViewBox.GetHeight());
- const char* pService;
- // now create shape
- if(aPoints.IsCurve())
+ // Is this correct? It overrides ViewBox stuff; OTOH it makes no
+ // sense to have the geometry content size different from object size
+ if(maSize.Width != 0 && maSize.Height != 0)
{
- if(aPoints.IsClosed())
- {
- pService = "com.sun.star.drawing.ClosedBezierShape";
- }
- else
- {
- pService = "com.sun.star.drawing.OpenBezierShape";
- }
- }
- else
- {
- if(aPoints.IsClosed())
- {
- pService = "com.sun.star.drawing.PolyPolygonShape";
- }
- else
- {
- pService = "com.sun.star.drawing.PolyLineShape";
- }
+ aSize = basegfx::B2DVector(maSize.Width, maSize.Height);
}
- // Add, set Style and properties from base shape
- AddShape(pService);
+ basegfx::B2DPolyPolygon aPolyPolygon;
- // #89344# test for mxShape.is() and not for mxShapes.is() to support
- // shape import helper classes WITHOUT XShapes (member mxShapes). This
- // is used by the writer.
- if( mxShape.is() )
+ if(basegfx::tools::importFromSvgD(aPolyPolygon, maD, true, 0))
{
- SetStyle();
- SetLayer();
-
- // set local parameters on shape
- uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
- if(xPropSet.is())
+ if(aPolyPolygon.count())
{
- uno::Any aAny;
+ const basegfx::B2DRange aSourceRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aSize.getX(), aViewBox.GetY() + aSize.getY());
- // set svg:d
- if(!maD.isEmpty())
+ if(!aSourceRange.equal(aTargetRange))
{
- if(aPoints.IsCurve())
- {
- drawing::PolyPolygonBezierCoords aSourcePolyPolygon(
- aPoints.GetPointSequenceSequence(),
- aPoints.GetFlagSequenceSequence());
+ aPolyPolygon.transform(
+ basegfx::tools::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
- aAny <<= aSourcePolyPolygon;
- xPropSet->setPropertyValue(
- OUString("Geometry"), aAny);
+ // create shape
+ const char* pService;
+
+ if(aPolyPolygon.areControlPointsUsed())
+ {
+ if(aPolyPolygon.isClosed())
+ {
+ pService = "com.sun.star.drawing.ClosedBezierShape";
}
else
{
- aAny <<= aPoints.GetPointSequenceSequence();
- xPropSet->setPropertyValue(
- OUString("Geometry"), aAny);
+ pService = "com.sun.star.drawing.OpenBezierShape";
+ }
+ }
+ else
+ {
+ if(aPolyPolygon.isClosed())
+ {
+ pService = "com.sun.star.drawing.PolyPolygonShape";
+ }
+ else
+ {
+ pService = "com.sun.star.drawing.PolyLineShape";
}
}
- }
- // set pos, size, shear and rotate
- SetTransformation();
+ // Add, set Style and properties from base shape
+ AddShape(pService);
- SdXMLShapeContext::StartElement(xAttrList);
+ // #89344# test for mxShape.is() and not for mxShapes.is() to support
+ // shape import helper classes WITHOUT XShapes (member mxShapes). This
+ // is used by the writer.
+ if( mxShape.is() )
+ {
+ SetStyle();
+ SetLayer();
+
+ // set local parameters on shape
+ uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
+
+ if(xPropSet.is())
+ {
+ uno::Any aAny;
+
+ // set polygon data
+ if(aPolyPolygon.areControlPointsUsed())
+ {
+ drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
+
+ basegfx::tools::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ aAny <<= aSourcePolyPolygon;
+ }
+ else
+ {
+ drawing::PointSequenceSequence aSourcePolyPolygon;
+
+ basegfx::tools::B2DPolyPolygonToUnoPointSequenceSequence(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ aAny <<= aSourcePolyPolygon;
+ }
+
+ xPropSet->setPropertyValue(OUString("Geometry"), aAny);
+ }
+
+ // set pos, size, shear and rotate
+ SetTransformation();
+
+ SdXMLShapeContext::StartElement(xAttrList);
+ }
+ }
}
}
}
@@ -1771,30 +1826,32 @@ void SdXMLConnectorShapeContext::processAttribute( sal_uInt16 nPrefix, const OUS
}
if( IsXMLToken( rLocalName, XML_D ) )
{
- SdXMLImExViewBox aViewBox( 0, 0, 1, 1 );
- awt::Point aPoint( 0, 0 );
- awt::Size aSize( 1, 1 );
-
- SdXMLImExSvgDElement aPoints( rValue, aViewBox, aPoint, aSize, GetImport() );
+ basegfx::B2DPolyPolygon aPolyPolygon;
- if ( aPoints.IsCurve() )
+ if(basegfx::tools::importFromSvgD(aPolyPolygon, rValue, true, 0))
{
- drawing::PolyPolygonBezierCoords aSourcePolyPolygon(
- aPoints.GetPointSequenceSequence(),
- aPoints.GetFlagSequenceSequence());
- maPath <<= aSourcePolyPolygon;
- }
- else
- {
- const drawing::PointSequenceSequence& rOuterSeq = aPoints.GetPointSequenceSequence();
- drawing::FlagSequenceSequence aFlagSeqSeq( rOuterSeq.getLength() );
- for ( int a = 0; a < rOuterSeq.getLength(); a++ )
- aFlagSeqSeq[ a ] = drawing::FlagSequence( rOuterSeq[ a ].getLength() );
+ if(aPolyPolygon.count())
+ {
+ // set polygon data
+ if(aPolyPolygon.areControlPointsUsed())
+ {
+ drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
- drawing::PolyPolygonBezierCoords aSourcePolyPolygon(
- aPoints.GetPointSequenceSequence(),
- aFlagSeqSeq );
- maPath <<= aSourcePolyPolygon;
+ basegfx::tools::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ maPath <<= aSourcePolyPolygon;
+ }
+ else
+ {
+ drawing::PointSequenceSequence aSourcePolyPolygon;
+
+ basegfx::tools::B2DPolyPolygonToUnoPointSequenceSequence(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ maPath <<= aSourcePolyPolygon;
+ }
+ }
}
}
}
@@ -3623,11 +3680,11 @@ void SdXMLCustomShapeContext::EndElement()
if(bFlippedX)
{
- aNewPoroperty.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MirroredX"));
+ aNewPoroperty.Name = "MirroredX";
}
else
{
- aNewPoroperty.Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MirroredY"));
+ aNewPoroperty.Name = "MirroredY";
}
aNewPoroperty.Handle = -1;
diff --git a/xmloff/source/style/MarkerStyle.cxx b/xmloff/source/style/MarkerStyle.cxx
index 125d411ab50c..b5f6fcdcdcd6 100644
--- a/xmloff/source/style/MarkerStyle.cxx
+++ b/xmloff/source/style/MarkerStyle.cxx
@@ -29,6 +29,9 @@
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
using namespace ::com::sun::star;
@@ -92,40 +95,37 @@ sal_Bool XMLMarkerStyleImport::importXML(
if( bHasViewBox && bHasPathData )
{
- SdXMLImExSvgDElement aPoints(strPathData, *pViewBox, awt::Point( 0, 0 ),
- awt::Size( pViewBox->GetWidth(), pViewBox->GetHeight() ), rImport );
+ basegfx::B2DPolyPolygon aPolyPolygon;
- if(aPoints.IsCurve())
+ if(basegfx::tools::importFromSvgD(aPolyPolygon, strPathData, true, 0))
{
- drawing::PolyPolygonBezierCoords aSourcePolyPolygon(
- aPoints.GetPointSequenceSequence(),
- aPoints.GetFlagSequenceSequence());
- rValue <<= aSourcePolyPolygon;
- }
- else
- {
- drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
- aSourcePolyPolygon.Coordinates = aPoints.GetPointSequenceSequence();
- aSourcePolyPolygon.Flags.realloc(aSourcePolyPolygon.Coordinates.getLength());
-
- // Zeiger auf innere sequences holen
- const drawing::PointSequence* pInnerSequence = aSourcePolyPolygon.Coordinates.getConstArray();
- drawing::FlagSequence* pInnerSequenceFlags = aSourcePolyPolygon.Flags.getArray();
-
- for(sal_Int32 a(0); a < aSourcePolyPolygon.Coordinates.getLength(); a++)
+ if(aPolyPolygon.count())
{
- pInnerSequenceFlags->realloc(pInnerSequence->getLength());
- drawing::PolygonFlags* pPolyFlags = pInnerSequenceFlags->getArray();
+ // ViewBox probably not used, but stay with former processing inside of
+ // SdXMLImExSvgDElement
+ const basegfx::B2DRange aSourceRange(
+ pViewBox->GetX(), pViewBox->GetY(),
+ pViewBox->GetX() + pViewBox->GetWidth(), pViewBox->GetY() + pViewBox->GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ 0.0, 0.0,
+ pViewBox->GetWidth(), pViewBox->GetHeight());
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolyPolygon.transform(
+ basegfx::tools::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
- for(sal_Int32 b(0); b < pInnerSequence->getLength(); b++)
- *pPolyFlags++ = drawing::PolygonFlags_NORMAL;
+ // always use PolyPolygonBezierCoords here
+ drawing::PolyPolygonBezierCoords aSourcePolyPolygon;
- // next run
- pInnerSequence++;
- pInnerSequenceFlags++;
+ basegfx::tools::B2DPolyPolygonToUnoPolyPolygonBezierCoords(
+ aPolyPolygon,
+ aSourcePolyPolygon);
+ rValue <<= aSourcePolyPolygon;
}
-
- rValue <<= aSourcePolyPolygon;
}
if( !aDisplayName.isEmpty() )
@@ -134,7 +134,6 @@ sal_Bool XMLMarkerStyleImport::importXML(
aDisplayName );
rStrName = aDisplayName;
}
-
}
if( pViewBox )
@@ -167,88 +166,44 @@ sal_Bool XMLMarkerStyleExport::exportXML(
if(rValue >>= aBezier)
{
// Name
- sal_Bool bEncoded = sal_False;
+ sal_Bool bEncoded(sal_False);
OUString aStrName( rStrName );
- rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
- rExport.EncodeStyleName( aStrName,
- &bEncoded ) );
- if( bEncoded )
- rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME,
- aStrName );
-
- // Viewbox (viewBox="0 0 1500 1000")
- sal_Int32 nMinX(0x7fffffff);
- sal_Int32 nMaxX(0x80000000);
- sal_Int32 nMinY(0x7fffffff);
- sal_Int32 nMaxY(0x80000000);
- sal_Int32 nOuterCnt(aBezier.Coordinates.getLength());
- drawing::PointSequence* pOuterSequence = aBezier.Coordinates.getArray();
- sal_Int32 a, b;
- sal_Bool bClosed(sal_False);
-
- for (a = 0; a < nOuterCnt; a++)
- {
- drawing::PointSequence* pSequence = pOuterSequence++;
- const awt::Point *pPoints = pSequence->getConstArray();
- sal_Int32 nPointCount(pSequence->getLength());
- if(nPointCount)
- {
- const awt::Point aStart = pPoints[0];
- const awt::Point aEnd = pPoints[nPointCount - 1];
-
- if(aStart.X == aEnd.X && aStart.Y == aEnd.Y)
- {
- bClosed = sal_True;
- }
- }
+ rExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, rExport.EncodeStyleName( aStrName, &bEncoded ) );
- for (b = 0; b < nPointCount; b++)
- {
- const awt::Point aPoint = pPoints[b];
-
- if( aPoint.X < nMinX )
- nMinX = aPoint.X;
-
- if( aPoint.X > nMaxX )
- nMaxX = aPoint.X;
-
- if( aPoint.Y < nMinY )
- nMinY = aPoint.Y;
-
- if( aPoint.Y > nMaxY )
- nMaxY = aPoint.Y;
- }
+ if( bEncoded )
+ {
+ rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_DISPLAY_NAME, aStrName );
}
- sal_Int32 nDifX(nMaxX - nMinX);
- sal_Int32 nDifY(nMaxY - nMinY);
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
+ aBezier));
+ const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
+
+ /////////////////
+ // Viewbox (viewBox="0 0 1500 1000")
- SdXMLImExViewBox aViewBox( 0, 0, nDifX, nDifY );
+ SdXMLImExViewBox aViewBox(
+ aPolyPolygonRange.getMinX(),
+ aPolyPolygonRange.getMinY(),
+ aPolyPolygonRange.getWidth(),
+ aPolyPolygonRange.getHeight());
rExport.AddAttribute( XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString() );
// Pathdata
- pOuterSequence = aBezier.Coordinates.getArray();
- drawing::FlagSequence* pOuterFlags = aBezier.Flags.getArray();
- SdXMLImExSvgDElement aSvgDElement(aViewBox, rExport);
-
- for (a = 0; a < nOuterCnt; a++)
- {
- drawing::PointSequence* pSequence = pOuterSequence++;
- drawing::FlagSequence* pFlags = pOuterFlags++;
-
- aSvgDElement.AddPolygon(pSequence, pFlags,
- awt::Point( 0, 0 ),
- awt::Size( aViewBox.GetWidth(), aViewBox.GetHeight() ),
- bClosed);
- }
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
// write point array
- rExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
+ rExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
// Do Write
- SvXMLElementExport rElem( rExport, XML_NAMESPACE_DRAW, XML_MARKER,
- sal_True, sal_False );
+ SvXMLElementExport rElem( rExport, XML_NAMESPACE_DRAW, XML_MARKER, sal_True, sal_False );
}
}
diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx
index 7a0ca85574a7..a8edd774cf1b 100644
--- a/xmloff/source/text/XMLTextFrameContext.cxx
+++ b/xmloff/source/text/XMLTextFrameContext.cxx
@@ -47,12 +47,14 @@
#include <xmloff/XMLEventsImportContext.hxx>
#include "XMLImageMapContext.hxx"
#include "XMLTextFrameContext.hxx"
-
#include "XMLTextListBlockContext.hxx"
#include "XMLTextListItemContext.hxx"
#include <xmloff/attrlist.hxx>
#include <comphelper/stl_types.hxx>
-
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <map>
using namespace ::com::sun::star;
@@ -283,31 +285,52 @@ XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
}
OUString sContourPolyPolygon("ContourPolyPolygon");
- Reference < XPropertySetInfo > xPropSetInfo =
- rPropSet->getPropertySetInfo();
- if( xPropSetInfo->hasPropertyByName(sContourPolyPolygon ) &&
- nWidth > 0 && nHeight > 0 && bPixelWidth == bPixelHeight &&
- !(bPath ? sD : sPoints).isEmpty() )
+ Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo();
+
+ if(xPropSetInfo->hasPropertyByName(sContourPolyPolygon) && nWidth > 0 && nHeight > 0 && bPixelWidth == bPixelHeight && (bPath ? sD : sPoints).getLength())
{
- awt::Point aPoint( 0, 0 );
- awt::Size aSize( nWidth, nHeight );
- SdXMLImExViewBox aViewBox( sViewBox,
- GetImport().GetMM100UnitConverter());
+ const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter());
+ basegfx::B2DPolyPolygon aPolyPolygon;
Any aAny;
+
if( bPath )
{
- SdXMLImExSvgDElement aPoints( sD, aViewBox, aPoint, aSize, GetImport() );
- aAny <<= aPoints.GetPointSequenceSequence();
+ basegfx::tools::importFromSvgD(aPolyPolygon, sD, true, 0);
}
else
{
- SdXMLImExPointsElement aPoints( sPoints, aViewBox, aPoint, aSize,
- GetImport().GetMM100UnitConverter() );
- aAny <<= aPoints.GetPointSequenceSequence();
+ basegfx::B2DPolygon aPolygon;
+
+ if(basegfx::tools::importFromSvgPoints(aPolygon, sPoints))
+ {
+ aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon);
+ }
}
- OUString sIsPixelContour("IsPixelContour");
- xPropSet->setPropertyValue( sContourPolyPolygon, aAny );
+ if(aPolyPolygon.count())
+ {
+ const basegfx::B2DRange aSourceRange(
+ aViewBox.GetX(), aViewBox.GetY(),
+ aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
+ const basegfx::B2DRange aTargetRange(
+ 0.0, 0.0,
+ nWidth, nHeight);
+
+ if(!aSourceRange.equal(aTargetRange))
+ {
+ aPolyPolygon.transform(
+ basegfx::tools::createSourceRangeTargetRangeTransform(
+ aSourceRange,
+ aTargetRange));
+ }
+
+ com::sun::star::drawing::PointSequenceSequence aPointSequenceSequence;
+ basegfx::tools::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence);
+ aAny <<= aPointSequenceSequence;
+ xPropSet->setPropertyValue( sContourPolyPolygon, aAny );
+ }
+
+ const OUString sIsPixelContour("IsPixelContour");
if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) )
{
@@ -315,7 +338,8 @@ XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
xPropSet->setPropertyValue( sIsPixelContour, aAny );
}
- OUString sIsAutomaticContour("IsAutomaticContour");
+ const OUString sIsAutomaticContour("IsAutomaticContour");
+
if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
{
aAny.setValue( &bAuto, ::getBooleanCppuType() );
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index 877d714edcb8..bc9820944274 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -21,11 +21,9 @@
#include <tools/debug.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/types.h>
-
#include <vector>
#include <list>
#include <boost/unordered_map.hpp>
-
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
@@ -59,15 +57,12 @@
#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/document/XRedlinesSupplier.hpp>
-
#include <com/sun/star/text/XBookmarksSupplier.hpp>
#include <com/sun/star/text/XFormField.hpp>
-
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/text/SectionFileLink.hpp>
#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/text/XTextShapesSupplier.hpp>
-
#include <com/sun/star/style/XAutoStylesSupplier.hpp>
#include <com/sun/star/style/XAutoStyleFamily.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
@@ -104,8 +99,10 @@
#include <xmloff/formlayerexport.hxx>
#include "XMLTextCharStyleNamesElementExport.hxx"
#include <comphelper/stlunosequence.hxx>
-
#include <xmloff/odffields.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/document/XStorageBasedDocument.hpp>
@@ -2964,38 +2961,29 @@ void XMLTextParagraphExport::_exportTextFrame(
}
void XMLTextParagraphExport::exportContour(
- const Reference < XPropertySet > & rPropSet,
- const Reference < XPropertySetInfo > & rPropSetInfo )
+ const Reference < XPropertySet > & rPropSet,
+ const Reference < XPropertySetInfo > & rPropSetInfo )
{
if( !rPropSetInfo->hasPropertyByName( sContourPolyPolygon ) )
+ {
return;
+ }
PointSequenceSequence aSourcePolyPolygon;
rPropSet->getPropertyValue( sContourPolyPolygon ) >>= aSourcePolyPolygon;
+ const basegfx::B2DPolyPolygon aPolyPolygon(
+ basegfx::tools::UnoPointSequenceSequenceToB2DPolyPolygon(
+ aSourcePolyPolygon));
+ const sal_uInt32 nPolygonCount(aPolyPolygon.count());
- if( !aSourcePolyPolygon.getLength() )
- return;
-
- awt::Point aPoint( 0, 0 );
- awt::Size aSize( 0, 0 );
- sal_Int32 nPolygons = aSourcePolyPolygon.getLength();
- const PointSequence *pPolygons = aSourcePolyPolygon.getConstArray();
- while( nPolygons-- )
+ if(!nPolygonCount)
{
- sal_Int32 nPoints = pPolygons->getLength();
- const awt::Point *pPoints = pPolygons->getConstArray();
- while( nPoints-- )
- {
- if( aSize.Width < pPoints->X )
- aSize.Width = pPoints->X;
- if( aSize.Height < pPoints->Y )
- aSize.Height = pPoints->Y;
- pPoints++;
- }
- pPolygons++;
+ return;
}
- sal_Bool bPixel = sal_False;
+ const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
+ bool bPixel(false);
+
if( rPropSetInfo->hasPropertyByName( sIsPixelContour ) )
{
bPixel = *(sal_Bool *)rPropSet->getPropertyValue( sIsPixelContour ).getValue();
@@ -3003,77 +2991,59 @@ void XMLTextParagraphExport::exportContour(
// svg: width
OUStringBuffer aStringBuffer( 10 );
- if( bPixel )
+
+ if(bPixel)
{
- ::sax::Converter::convertMeasurePx(aStringBuffer, aSize.Width);
+ ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
}
else
{
- GetExport().GetMM100UnitConverter().convertMeasureToXML(
- aStringBuffer, aSize.Width);
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
}
- GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
- aStringBuffer.makeStringAndClear() );
+
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
// svg: height
- if( bPixel )
+ if(bPixel)
{
- ::sax::Converter::convertMeasurePx(aStringBuffer, aSize.Height);
+ ::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
}
else
{
- GetExport().GetMM100UnitConverter().convertMeasureToXML(
- aStringBuffer, aSize.Height);
+ GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
}
- GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
- aStringBuffer.makeStringAndClear() );
-
- // svg:viewbox
- SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
- GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
- aViewBox.GetExportString());
- sal_Int32 nOuterCnt( aSourcePolyPolygon.getLength() );
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
+ // svg:viewbox
+ SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
+ GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
- if( 1L == nOuterCnt )
+
+ if(1 == nPolygonCount )
{
// simple polygon shape, can be written as svg:points sequence
- /*const*/ PointSequence* pSequence =
- (PointSequence*)aSourcePolyPolygon.getConstArray();
-
- SdXMLImExPointsElement aPoints( pSequence, aViewBox, aPoint, aSize );
+ const OUString aPointString(
+ basegfx::tools::exportToSvgPoints(
+ aPolyPolygon.getB2DPolygon(0)));
// write point array
- GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_POINTS,
- aPoints.GetExportString());
+ GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
eElem = XML_CONTOUR_POLYGON;
}
else
{
// polypolygon, needs to be written as a svg:path sequence
- /*const*/ PointSequence* pOuterSequence =
- (PointSequence*)aSourcePolyPolygon.getConstArray();
- if(pOuterSequence)
- {
- // prepare svx:d element export
- SdXMLImExSvgDElement aSvgDElement( aViewBox, GetExport() );
+ const OUString aPolygonString(
+ basegfx::tools::exportToSvgD(
+ aPolyPolygon,
+ true, // bUseRelativeCoordinates
+ false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
+ true)); // bHandleRelativeNextPointCompatible
- for(sal_Int32 a(0L); a < nOuterCnt; a++)
- {
- /*const*/ PointSequence* pSequence = pOuterSequence++;
- if(pSequence)
- {
- aSvgDElement.AddPolygon(pSequence, 0L, aPoint,
- aSize, sal_True );
- }
- }
-
- // write point array
- GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D,
- aSvgDElement.GetExportString());
- eElem = XML_CONTOUR_PATH;
- }
+ // write point array
+ GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
+ eElem = XML_CONTOUR_PATH;
}
if( rPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )