summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Hung <marklh9@gmail.com>2018-08-10 22:15:36 +0800
committerMark Hung <marklh9@gmail.com>2018-08-14 18:23:14 +0200
commit071d8aff7cbe38c0522c5a87ee77dd1b0d2da91f (patch)
tree06573ad518a95d6d7e0126eb195b80e079db5d4a
parent652454378c5e77e11d9fb9cc399ccb74387a0229 (diff)
tdf#118825 Implement OOXMLMotionPath in exportToSvgD of basegfx.
Powerpoint only allows M,L,C,Z,E,m,l,c,z,e , i.e. V,H,S ( and their corresponding relative command ) must not be used and ending E is mandatory. Command and space delimiters also can not be skipped. Change-Id: Icad38ec2eed3e49143eb9a03aa56cc178baae99d Reviewed-on: https://gerrit.libreoffice.org/58848 Tested-by: Jenkins Reviewed-by: Mark Hung <marklh9@gmail.com>
-rw-r--r--basegfx/source/polygon/b2dsvgpolypolygon.cxx96
-rw-r--r--include/basegfx/polygon/b2dpolypolygontools.hxx9
2 files changed, 57 insertions, 48 deletions
diff --git a/basegfx/source/polygon/b2dsvgpolypolygon.cxx b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
index a0ff38155a26..2a195641d5f0 100644
--- a/basegfx/source/polygon/b2dsvgpolypolygon.cxx
+++ b/basegfx/source/polygon/b2dsvgpolypolygon.cxx
@@ -32,31 +32,28 @@
namespace
{
-void putCommandChar(OUStringBuffer& rBuffer,sal_Unicode& rLastSVGCommand, sal_Unicode aChar, bool bToLower)
+void putCommandChar(OUStringBuffer& rBuffer,sal_Unicode& rLastSVGCommand, sal_Unicode aChar, bool bToLower,bool bVerbose)
{
const sal_Unicode aCommand = bToLower ? rtl::toAsciiLowerCase(aChar) : aChar;
- if (rLastSVGCommand != aCommand)
+ if (bVerbose && rBuffer.getLength())
+ rBuffer.append(' ');
+
+ if (bVerbose || rLastSVGCommand != aCommand)
{
rBuffer.append(aCommand);
rLastSVGCommand = aCommand;
}
}
-void putNumberChar(OUStringBuffer& rStr,double fValue, double fOldValue, bool bUseRelativeCoordinates)
+void putNumberChar(OUStringBuffer& rStr,double fValue, double fOldValue, bool bUseRelativeCoordinates,bool bVerbose)
{
if (bUseRelativeCoordinates)
fValue -= fOldValue;
const sal_Int32 aLen(rStr.getLength());
- if (aLen)
- {
- if (basegfx::internal::isOnNumberChar(rStr[aLen - 1], false) &&
- fValue >= 0.0 )
- {
- rStr.append(' ');
- }
- }
+ if (bVerbose || (aLen && basegfx::internal::isOnNumberChar(rStr[aLen - 1], false) && fValue >= 0.0))
+ rStr.append(' ');
rStr.append(fValue);
}
@@ -727,7 +724,8 @@ namespace basegfx
const B2DPolyPolygon& rPolyPolygon,
bool bUseRelativeCoordinates,
bool bDetectQuadraticBeziers,
- bool bHandleRelativeNextPointCompatible)
+ bool bHandleRelativeNextPointCompatible,
+ bool bOOXMLMotionPath)
{
const sal_uInt32 nCount(rPolyPolygon.count());
OUStringBuffer aResult;
@@ -758,9 +756,9 @@ namespace basegfx
}
// Write 'moveto' and the 1st coordinates, set aLastSVGCommand to 'lineto'
- putCommandChar(aResult, aLastSVGCommand, 'M', bUseRelativeCoordinatesForFirstPoint);
- putNumberChar(aResult, aEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinatesForFirstPoint);
- putNumberChar(aResult, aEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinatesForFirstPoint);
+ putCommandChar(aResult, aLastSVGCommand, 'M', bUseRelativeCoordinatesForFirstPoint, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinatesForFirstPoint, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinatesForFirstPoint, bOOXMLMotionPath);
aLastSVGCommand = bUseRelativeCoordinatesForFirstPoint ? 'l' : 'L';
aCurrentSVGPosition = aEdgeStart;
@@ -793,7 +791,7 @@ namespace basegfx
// That's what is done from our import, so avoid exporting it as first statement
// is necessary.
const bool bSymmetricAtEdgeStart(
- nIndex != 0
+ !bOOXMLMotionPath && nIndex != 0
&& aPolygon.getContinuityInPoint(nIndex) == B2VectorContinuity::C2);
if(bDetectQuadraticBeziers)
@@ -815,20 +813,20 @@ namespace basegfx
// approximately equal, export as quadratic bezier
if(bSymmetricAtEdgeStart)
{
- putCommandChar(aResult, aLastSVGCommand, 'T', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'T', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
else
{
- putCommandChar(aResult, aLastSVGCommand, 'Q', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'Q', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aLeft.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aLeft.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aLeft.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aLeft.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
}
@@ -837,24 +835,24 @@ namespace basegfx
// export as cubic bezier
if(bSymmetricAtEdgeStart)
{
- putCommandChar(aResult, aLastSVGCommand, 'S', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'S', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
else
{
- putCommandChar(aResult, aLastSVGCommand, 'C', bUseRelativeCoordinates);
-
- putNumberChar(aResult, aControlEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aControlEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- putNumberChar(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'C', bUseRelativeCoordinates, bOOXMLMotionPath);
+
+ putNumberChar(aResult, aControlEdgeStart.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aControlEdgeStart.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aControlEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aControlEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
}
@@ -876,29 +874,29 @@ namespace basegfx
{
// point is a double point; do not export at all
}
- else if(bXEqual)
+ else if(bXEqual && !bOOXMLMotionPath)
{
// export as vertical line
- putCommandChar(aResult, aLastSVGCommand, 'V', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'V', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
- else if(bYEqual)
+ else if(bYEqual && !bOOXMLMotionPath)
{
// export as horizontal line
- putCommandChar(aResult, aLastSVGCommand, 'H', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'H', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
else
{
// export as line
- putCommandChar(aResult, aLastSVGCommand, 'L', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'L', bUseRelativeCoordinates, bOOXMLMotionPath);
- putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates);
- putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates);
+ putNumberChar(aResult, aEdgeEnd.getX(), aCurrentSVGPosition.getX(), bUseRelativeCoordinates, bOOXMLMotionPath);
+ putNumberChar(aResult, aEdgeEnd.getY(), aCurrentSVGPosition.getY(), bUseRelativeCoordinates, bOOXMLMotionPath);
aCurrentSVGPosition = aEdgeEnd;
}
}
@@ -911,7 +909,11 @@ namespace basegfx
// close path if closed poly (Z and z are equivalent here, but looks nicer when case is matched)
if(aPolygon.isClosed())
{
- putCommandChar(aResult, aLastSVGCommand, 'Z', bUseRelativeCoordinates);
+ putCommandChar(aResult, aLastSVGCommand, 'Z', bUseRelativeCoordinates, bOOXMLMotionPath);
+ }
+ else if (bOOXMLMotionPath)
+ {
+ putCommandChar(aResult, aLastSVGCommand, 'E', bUseRelativeCoordinates, bOOXMLMotionPath);
}
if(!bHandleRelativeNextPointCompatible)
diff --git a/include/basegfx/polygon/b2dpolypolygontools.hxx b/include/basegfx/polygon/b2dpolypolygontools.hxx
index 8de5e6c90cc3..b14d003be4a4 100644
--- a/include/basegfx/polygon/b2dpolypolygontools.hxx
+++ b/include/basegfx/polygon/b2dpolypolygontools.hxx
@@ -228,6 +228,12 @@ namespace basegfx
polygon is kept; this is needed to read odf files.
If false, pure svg is used; this is needed for svg import.
+ @param bOOXMLMotionPath
+ If set to true, export string format that is acceptable for
+ for animation motion path for PowerPoint: always space delimited,
+ never neglect command char, always end with E, and do not export
+ H or V.
+
@return the generated SVG-D statement (the XML d attribute
value alone, without any "<path ...>" or "d="...")
*/
@@ -235,7 +241,8 @@ namespace basegfx
const B2DPolyPolygon& rPolyPoly,
bool bUseRelativeCoordinates,
bool bDetectQuadraticBeziers,
- bool bHandleRelativeNextPointCompatible);
+ bool bHandleRelativeNextPointCompatible,
+ bool bOOXMLMotionPath = false);
// #i76891# Try to remove existing curve segments if they are simply edges
BASEGFX_DLLPUBLIC B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate);