summaryrefslogtreecommitdiff
path: root/basegfx/source
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 /basegfx/source
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
Diffstat (limited to 'basegfx/source')
-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
6 files changed, 1056 insertions, 293 deletions
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: */