Files
libreoffice/xmloff/source/draw/xexptran.cxx

3150 lines
122 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* $RCSfile: xexptran.cxx,v $
2000-09-18 16:07:07 +00:00
*
* $Revision: 1.28 $
2000-09-18 16:07:07 +00:00
*
* last change: $Author: rt $ $Date: 2008-03-12 10:36:50 $
2000-09-18 16:07:07 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 16:07:07 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 16:07:07 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 16:07:07 +00:00
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2000-09-18 16:07:07 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 16:07:07 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
2000-09-18 16:07:07 +00:00
#ifndef _XEXPTRANSFORM_HXX
#include "xexptran.hxx"
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SV_SALBTYPE_HXX
#include <vcl/salbtype.hxx>
#endif
#ifndef _BGFX_VECTOR_B2DVECTOR_HXX
#include <basegfx/vector/b2dvector.hxx>
#endif
#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif
#ifndef _BGFX_TUPLE_B3DTUPLE_HXX
#include <basegfx/tuple/b3dtuple.hxx>
#endif
#ifndef _BGFX_MATRIX_B3DHOMMATRIX_HXX
#include <basegfx/matrix/b3dhommatrix.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
2000-09-18 16:07:07 +00:00
using namespace ::com::sun::star;
//////////////////////////////////////////////////////////////////////////////
// Defines
#define BORDER_INTEGERS_ARE_EQUAL (4)
//////////////////////////////////////////////////////////////////////////////
// Predeclarations
void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen);
void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection);
2000-09-18 16:07:07 +00:00
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// parsing help functions for simple chars
void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
while(rPos < nLen
&& sal_Unicode(' ') == rStr[rPos])
2000-09-18 16:07:07 +00:00
rPos++;
}
void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
while(rPos < nLen
&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos]))
2000-09-18 16:07:07 +00:00
rPos++;
}
void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
while(rPos < nLen
&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos]))
2000-09-18 16:07:07 +00:00
rPos++;
}
void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
while(rPos < nLen
&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos]))
2000-09-18 16:07:07 +00:00
rPos++;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// parsing help functions for integer numbers
bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
2000-09-18 16:07:07 +00:00
{
sal_Unicode aChar(rStr[nPos]);
2000-09-18 16:07:07 +00:00
if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
|| (bSignAllowed && sal_Unicode('+') == aChar)
|| (bSignAllowed && sal_Unicode('-') == aChar)
2000-09-18 16:07:07 +00:00
)
return true;
return false;
2000-09-18 16:07:07 +00:00
}
bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos)
{
sal_Unicode aChar(rStr[nPos]);
if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
|| (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
|| sal_Unicode('%') == aChar
)
return true;
return false;
}
void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
bool bSignAllowed(true);
2000-09-18 16:07:07 +00:00
while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed))
2000-09-18 16:07:07 +00:00
{
bSignAllowed = false;
2000-09-18 16:07:07 +00:00
rPos++;
}
}
void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
const sal_Int32 nLen)
2000-09-18 16:07:07 +00:00
{
Imp_SkipNumber(rStr, rPos, nLen);
Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
2000-09-18 16:07:07 +00:00
}
// #100617# Allow to skip doubles, too.
void Imp_SkipDoubleAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
const sal_Int32 nLen)
{
Imp_SkipDouble(rStr, rPos, nLen);
Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
}
void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue)
2000-12-07 14:15:53 +00:00
{
OUStringBuffer sStringBuffer;
SvXMLUnitConverter::convertNumber(sStringBuffer, nValue);
rStr += OUString(sStringBuffer.makeStringAndClear());
2000-09-18 16:07:07 +00:00
}
void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue)
{
const sal_Int32 aLen(rStr.getLength());
if(aLen)
if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0)
rStr += String(sal_Unicode(' '));
Imp_PutNumberChar(rStr, nValue);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// parsing help functions for double numbers
void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32)
{
sal_Unicode aChar(rStr[rPos]);
if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
aChar = rStr[++rPos];
while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
|| sal_Unicode('.') == aChar)
{
aChar = rStr[++rPos];
}
if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
{
aChar = rStr[++rPos];
if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
aChar = rStr[++rPos];
while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
{
aChar = rStr[++rPos];
}
}
}
double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen,
const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
{
sal_Unicode aChar(rStr[rPos]);
OUStringBuffer sNumberString;
if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
{
sNumberString.append(rStr[rPos]);
aChar = rStr[++rPos];
}
while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
|| sal_Unicode('.') == aChar)
{
sNumberString.append(rStr[rPos]);
aChar = rStr[++rPos];
}
if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
{
sNumberString.append(rStr[rPos]);
aChar = rStr[++rPos];
if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
{
sNumberString.append(rStr[rPos]);
aChar = rStr[++rPos];
}
while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
{
sNumberString.append(rStr[rPos]);
aChar = rStr[++rPos];
}
}
if(bLookForUnits)
{
Imp_SkipSpaces(rStr, rPos, nLen);
while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
sNumberString.append(rStr[rPos++]);
}
if(sNumberString.getLength())
{
if(bLookForUnits)
rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true);
else
rConv.convertDouble(fRetval, sNumberString.makeStringAndClear());
}
return fRetval;
}
void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
bool bConvertUnits = false)
2000-09-18 16:07:07 +00:00
{
OUStringBuffer sStringBuffer;
if(bConvertUnits)
rConv.convertDouble(sStringBuffer, fValue, true);
else
rConv.convertDouble(sStringBuffer, fValue);
rStr += OUString(sStringBuffer.makeStringAndClear());
2000-09-18 16:07:07 +00:00
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
2000-11-24 16:51:07 +00:00
// base class of all 2D transform objects
2000-09-18 16:07:07 +00:00
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
sal_uInt16 mnType;
2000-11-24 16:51:07 +00:00
ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
2000-09-18 16:07:07 +00:00
: mnType(nType) {}
};
2000-11-24 16:51:07 +00:00
//////////////////////////////////////////////////////////////////////////////
// possible object types for 2D
#define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000
#define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001
#define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002
#define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003
#define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004
#define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005
2000-09-18 16:07:07 +00:00
//////////////////////////////////////////////////////////////////////////////
// classes of objects, different sizes
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
double mfRotate;
2000-11-24 16:51:07 +00:00
ImpSdXMLExpTransObj2DRotate(double fVal)
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {}
2000-09-18 16:07:07 +00:00
};
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DTuple maScale;
ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {}
2000-09-18 16:07:07 +00:00
};
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DTuple maTranslate;
ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {}
2000-09-18 16:07:07 +00:00
};
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
double mfSkewX;
2000-11-24 16:51:07 +00:00
ImpSdXMLExpTransObj2DSkewX(double fVal)
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {}
2000-09-18 16:07:07 +00:00
};
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
double mfSkewY;
2000-11-24 16:51:07 +00:00
ImpSdXMLExpTransObj2DSkewY(double fVal)
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {}
2000-09-18 16:07:07 +00:00
};
2000-11-24 16:51:07 +00:00
struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DHomMatrix maMatrix;
ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {}
2000-09-18 16:07:07 +00:00
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
2000-11-24 16:51:07 +00:00
// delete all entries in list
2000-09-18 16:07:07 +00:00
2000-11-24 16:51:07 +00:00
void SdXMLImExTransform2D::EmptyList()
2000-09-18 16:07:07 +00:00
{
for(sal_uInt32 a(0L); a < maList.size(); a++)
2000-09-18 16:07:07 +00:00
{
ImpSdXMLExpTransObj2DBase* pObj = maList[a];
2000-09-18 16:07:07 +00:00
switch(pObj->mnType)
{
case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
{
delete (ImpSdXMLExpTransObj2DRotate*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
{
delete (ImpSdXMLExpTransObj2DScale*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
{
delete (ImpSdXMLExpTransObj2DTranslate*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
{
delete (ImpSdXMLExpTransObj2DSkewX*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
{
delete (ImpSdXMLExpTransObj2DSkewY*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
{
delete (ImpSdXMLExpTransObj2DMatrix*)pObj;
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
break;
}
2000-09-18 16:07:07 +00:00
}
}
maList.clear();
2000-09-18 16:07:07 +00:00
}
//////////////////////////////////////////////////////////////////////////////
// add members
2000-11-24 16:51:07 +00:00
void SdXMLImExTransform2D::AddRotate(double fNew)
2000-09-18 16:07:07 +00:00
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew));
2000-09-18 16:07:07 +00:00
}
void SdXMLImExTransform2D::AddScale(const ::basegfx::B2DTuple& rNew)
2000-09-18 16:07:07 +00:00
{
if(1.0 != rNew.getX() || 1.0 != rNew.getY())
maList.push_back(new ImpSdXMLExpTransObj2DScale(rNew));
2000-09-18 16:07:07 +00:00
}
void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
2000-09-18 16:07:07 +00:00
{
if(!rNew.equalZero())
maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew));
2000-09-18 16:07:07 +00:00
}
2000-11-24 16:51:07 +00:00
void SdXMLImExTransform2D::AddSkewX(double fNew)
2000-09-18 16:07:07 +00:00
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew));
2000-09-18 16:07:07 +00:00
}
2000-11-24 16:51:07 +00:00
void SdXMLImExTransform2D::AddSkewY(double fNew)
2000-09-18 16:07:07 +00:00
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fNew));
2000-09-18 16:07:07 +00:00
}
void SdXMLImExTransform2D::AddMatrix(const ::basegfx::B2DHomMatrix& rNew)
2000-09-18 16:07:07 +00:00
{
if(!rNew.isIdentity())
maList.push_back(new ImpSdXMLExpTransObj2DMatrix(rNew));
2000-09-18 16:07:07 +00:00
}
//////////////////////////////////////////////////////////////////////////////
// gen string for export
2000-11-24 16:51:07 +00:00
const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv)
2000-09-18 16:07:07 +00:00
{
OUString aNewString;
OUString aClosingBrace(sal_Unicode(')'));
OUString aEmptySpace(sal_Unicode(' '));
2000-09-18 16:07:07 +00:00
for(sal_uInt32 a(0UL); a < maList.size(); a++)
2000-09-18 16:07:07 +00:00
{
ImpSdXMLExpTransObj2DBase* pObj = maList[a];
2000-09-18 16:07:07 +00:00
switch(pObj->mnType)
{
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("rotate (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate);
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("scale (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX());
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY());
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("translate (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true);
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true);
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("skewX (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX);
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("skewY (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY);
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
2000-09-18 16:07:07 +00:00
{
aNewString += OUString::createFromAscii("matrix (");
// a
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0));
aNewString += aEmptySpace;
// b
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0));
aNewString += aEmptySpace;
// c
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1));
aNewString += aEmptySpace;
// d
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1));
aNewString += aEmptySpace;
// e
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true);
aNewString += aEmptySpace;
// f
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true);
aNewString += aClosingBrace;
2000-09-18 16:07:07 +00:00
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
break;
}
2000-09-18 16:07:07 +00:00
}
// if not the last entry, add one space to next tag
if(a + 1UL != maList.size())
{
aNewString += aEmptySpace;
}
2000-09-18 16:07:07 +00:00
}
// fill string form OUString
msString = aNewString;
2000-09-18 16:07:07 +00:00
return msString;
}
//////////////////////////////////////////////////////////////////////////////
// for Import: constructor with string, parses it and generates entries
2000-11-24 16:51:07 +00:00
SdXMLImExTransform2D::SdXMLImExTransform2D(const OUString& rNew, const SvXMLUnitConverter& rConv)
2000-09-18 16:07:07 +00:00
{
SetString(rNew, rConv);
}
//////////////////////////////////////////////////////////////////////////////
// sets new string, parses it and generates entries
void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
{
msString = rNew;
EmptyList();
2000-09-18 16:07:07 +00:00
if(msString.getLength())
{
const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
const sal_Int32 nLen(aStr.getLength());
const OUString aString_rotate(OUString::createFromAscii("rotate"));
const OUString aString_scale(OUString::createFromAscii("scale"));
const OUString aString_translate(OUString::createFromAscii("translate"));
const OUString aString_skewX(OUString::createFromAscii("skewX"));
const OUString aString_skewY(OUString::createFromAscii("skewY"));
const OUString aString_matrix(OUString::createFromAscii("matrix"));
sal_Int32 nPos(0);
2000-09-18 16:07:07 +00:00
while(nPos < nLen)
{
// skip spaces
Imp_SkipSpaces(aStr, nPos, nLen);
// look for tag
if(nPos < nLen)
{
if(nPos == aStr.indexOf(aString_rotate, nPos))
2000-09-18 16:07:07 +00:00
{
double fValue(0.0);
2000-11-24 16:51:07 +00:00
nPos += 6;
2000-09-18 16:07:07 +00:00
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
2000-09-18 16:07:07 +00:00
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue));
2000-09-18 16:07:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_scale, nPos))
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DTuple aValue(1.0, 1.0);
2000-11-24 16:51:07 +00:00
nPos += 5;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue));
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
else if(nPos == aStr.indexOf(aString_translate, nPos))
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DTuple aValue;
2000-11-24 16:51:07 +00:00
nPos += 9;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
if(!aValue.equalZero())
maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue));
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
else if(nPos == aStr.indexOf(aString_skewX, nPos))
2000-09-18 16:07:07 +00:00
{
double fValue(0.0);
2000-11-24 16:51:07 +00:00
nPos += 5;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue));
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
else if(nPos == aStr.indexOf(aString_skewY, nPos))
2000-09-18 16:07:07 +00:00
{
double fValue(0.0);
2000-11-24 16:51:07 +00:00
nPos += 5;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue));
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
else if(nPos == aStr.indexOf(aString_matrix, nPos))
2000-09-18 16:07:07 +00:00
{
::basegfx::B2DHomMatrix aValue;
2000-11-24 16:51:07 +00:00
nPos += 6;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
// a
aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// b
aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// c
aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// d
aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// e
aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// f
aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
if(!aValue.isIdentity())
maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue));
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
else
{
2000-09-18 16:07:07 +00:00
nPos++;
}
2000-09-18 16:07:07 +00:00
}
}
}
}
void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans)
{
rFullTrans.identity();
for(sal_uInt32 a(0L); a < maList.size(); a++)
{
ImpSdXMLExpTransObj2DBase* pObj = maList[a];
switch(pObj->mnType)
{
case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
{
// #i78696#
// mfRotate is mathematically wrong oriented since we export/import the angle
// values mirrored. This error is fixed in the API, but not yet in the FileFormat.
// For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
// ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
// to mirror the value here
rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0);
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
{
const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale;
rFullTrans.scale(rScale.getX(), rScale.getY());
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
{
const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate;
rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
{
rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX));
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
{
rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY));
break;
}
case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
{
rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix;
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
break;
}
}
}
}
2000-11-24 16:51:07 +00:00
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// base class of all 3D transform objects
struct ImpSdXMLExpTransObj3DBase
{
sal_uInt16 mnType;
ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
: mnType(nType) {}
};
//////////////////////////////////////////////////////////////////////////////
// possible object types for 3D
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001
#define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002
#define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003
#define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004
#define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005
//////////////////////////////////////////////////////////////////////////////
// classes of objects, different sizes
struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
{
double mfRotateX;
ImpSdXMLExpTransObj3DRotateX(double fVal)
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {}
};
struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
{
double mfRotateY;
ImpSdXMLExpTransObj3DRotateY(double fVal)
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {}
};
struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
{
double mfRotateZ;
ImpSdXMLExpTransObj3DRotateZ(double fVal)
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {}
};
struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
{
::basegfx::B3DTuple maScale;
ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {}
};
struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
{
::basegfx::B3DTuple maTranslate;
ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {}
};
struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
{
::basegfx::B3DHomMatrix maMatrix;
ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
2000-11-24 16:51:07 +00:00
: ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {}
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// delete all entries in list
void SdXMLImExTransform3D::EmptyList()
{
for(sal_uInt32 a(0L); a< maList.size(); a++)
2000-11-24 16:51:07 +00:00
{
ImpSdXMLExpTransObj3DBase* pObj = maList[a];
2000-11-24 16:51:07 +00:00
switch(pObj->mnType)
{
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
{
delete (ImpSdXMLExpTransObj3DRotateX*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
{
delete (ImpSdXMLExpTransObj3DRotateY*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
{
delete (ImpSdXMLExpTransObj3DRotateZ*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
{
delete (ImpSdXMLExpTransObj3DScale*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
{
delete (ImpSdXMLExpTransObj3DTranslate*)pObj;
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
{
delete (ImpSdXMLExpTransObj3DMatrix*)pObj;
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
break;
}
2000-11-24 16:51:07 +00:00
}
}
maList.clear();
2000-11-24 16:51:07 +00:00
}
//////////////////////////////////////////////////////////////////////////////
// add members
void SdXMLImExTransform3D::AddRotateX(double fNew)
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddRotateY(double fNew)
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddRotateZ(double fNew)
{
if(fNew != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddScale(const ::basegfx::B3DTuple& rNew)
2000-11-24 16:51:07 +00:00
{
if(1.0 != rNew.getX() || 1.0 != rNew.getY() || 1.0 != rNew.getZ())
maList.push_back(new ImpSdXMLExpTransObj3DScale(rNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddTranslate(const ::basegfx::B3DTuple& rNew)
2000-11-24 16:51:07 +00:00
{
if(!rNew.equalZero())
maList.push_back(new ImpSdXMLExpTransObj3DTranslate(rNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
2000-11-24 16:51:07 +00:00
{
if(!rNew.isIdentity())
maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew));
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
{
::basegfx::B3DHomMatrix aExportMatrix;
aExportMatrix.set(0, 0, xHomMat.Line1.Column1);
aExportMatrix.set(0, 1, xHomMat.Line1.Column2);
aExportMatrix.set(0, 2, xHomMat.Line1.Column3);
aExportMatrix.set(0, 3, xHomMat.Line1.Column4);
aExportMatrix.set(1, 0, xHomMat.Line2.Column1);
aExportMatrix.set(1, 1, xHomMat.Line2.Column2);
aExportMatrix.set(1, 2, xHomMat.Line2.Column3);
aExportMatrix.set(1, 3, xHomMat.Line2.Column4);
aExportMatrix.set(2, 0, xHomMat.Line3.Column1);
aExportMatrix.set(2, 1, xHomMat.Line3.Column2);
aExportMatrix.set(2, 2, xHomMat.Line3.Column3);
aExportMatrix.set(2, 3, xHomMat.Line3.Column4);
2000-11-24 16:51:07 +00:00
AddMatrix(aExportMatrix);
}
//////////////////////////////////////////////////////////////////////////////
// gen string for export
const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv)
{
OUString aNewString;
OUString aClosingBrace(sal_Unicode(')'));
OUString aEmptySpace(sal_Unicode(' '));
2000-11-24 16:51:07 +00:00
for(sal_uInt32 a(0UL); a < maList.size(); a++)
2000-11-24 16:51:07 +00:00
{
ImpSdXMLExpTransObj3DBase* pObj = maList[a];
2000-11-24 16:51:07 +00:00
switch(pObj->mnType)
{
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
{
aNewString += OUString::createFromAscii("rotatex (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX);
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
{
aNewString += OUString::createFromAscii("rotatey (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY);
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
{
aNewString += OUString::createFromAscii("rotatez (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
{
aNewString += OUString::createFromAscii("scale (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX());
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY());
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ());
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
{
aNewString += OUString::createFromAscii("translate (");
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true);
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true);
aNewString += aEmptySpace;
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true);
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
{
aNewString += OUString::createFromAscii("matrix (");
// a
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0));
aNewString += aEmptySpace;
// b
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0));
aNewString += aEmptySpace;
// c
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0));
aNewString += aEmptySpace;
// d
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1));
aNewString += aEmptySpace;
// e
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1));
aNewString += aEmptySpace;
// f
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1));
aNewString += aEmptySpace;
// g
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2));
aNewString += aEmptySpace;
// h
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2));
aNewString += aEmptySpace;
// i
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2));
aNewString += aEmptySpace;
// j
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true);
aNewString += aEmptySpace;
// k
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true);
aNewString += aEmptySpace;
// l
Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true);
aNewString += aClosingBrace;
2000-11-24 16:51:07 +00:00
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
break;
}
2000-11-24 16:51:07 +00:00
}
// if not the last entry, add one space to next tag
if(a + 1UL != maList.size())
{
aNewString += aEmptySpace;
}
2000-11-24 16:51:07 +00:00
}
// fill string form OUString
msString = aNewString;
2000-11-24 16:51:07 +00:00
return msString;
}
//////////////////////////////////////////////////////////////////////////////
// for Import: constructor with string, parses it and generates entries
SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv)
{
SetString(rNew, rConv);
}
//////////////////////////////////////////////////////////////////////////////
// sets new string, parses it and generates entries
void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
{
msString = rNew;
EmptyList();
2000-11-24 16:51:07 +00:00
if(msString.getLength())
{
const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
const sal_Int32 nLen(aStr.getLength());
const OUString aString_rotatex(OUString::createFromAscii("rotatex"));
const OUString aString_rotatey(OUString::createFromAscii("rotatey"));
const OUString aString_rotatez(OUString::createFromAscii("rotatez"));
const OUString aString_scale(OUString::createFromAscii("scale"));
const OUString aString_translate(OUString::createFromAscii("translate"));
const OUString aString_matrix(OUString::createFromAscii("matrix"));
sal_Int32 nPos(0);
2000-11-24 16:51:07 +00:00
while(nPos < nLen)
{
// skip spaces
Imp_SkipSpaces(aStr, nPos, nLen);
// look for tag
if(nPos < nLen)
{
if(nPos == aStr.indexOf(aString_rotatex, nPos))
2000-11-24 16:51:07 +00:00
{
double fValue(0.0);
nPos += 7;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
2000-11-24 16:51:07 +00:00
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_rotatey, nPos))
2000-11-24 16:51:07 +00:00
{
double fValue(0.0);
nPos += 7;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
2000-11-24 16:51:07 +00:00
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_rotatez, nPos))
2000-11-24 16:51:07 +00:00
{
double fValue(0.0);
nPos += 7;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
2000-11-24 16:51:07 +00:00
if(fValue != 0.0)
maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_scale, nPos))
2000-11-24 16:51:07 +00:00
{
::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
2000-11-24 16:51:07 +00:00
nPos += 5;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
2000-11-24 16:51:07 +00:00
if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_translate, nPos))
2000-11-24 16:51:07 +00:00
{
::basegfx::B3DTuple aValue;
2000-11-24 16:51:07 +00:00
nPos += 9;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
2000-11-24 16:51:07 +00:00
if(!aValue.equalZero())
maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else if(nPos == aStr.indexOf(aString_matrix, nPos))
2000-11-24 16:51:07 +00:00
{
::basegfx::B3DHomMatrix aValue;
2000-11-24 16:51:07 +00:00
nPos += 6;
Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
// a
aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// b
aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// c
aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// d
aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// e
aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// f
aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// g
aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// h
aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// i
aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// j
aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// k
aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// l
aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
2000-11-24 16:51:07 +00:00
if(!aValue.isIdentity())
maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue));
2000-11-24 16:51:07 +00:00
Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
}
else
{
2000-11-24 16:51:07 +00:00
nPos++;
}
2000-11-24 16:51:07 +00:00
}
}
}
}
bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat)
2000-11-24 16:51:07 +00:00
{
::basegfx::B3DHomMatrix aFullTransform;
2000-11-24 16:51:07 +00:00
GetFullTransform(aFullTransform);
if(!aFullTransform.isIdentity())
2000-11-24 16:51:07 +00:00
{
xHomMat.Line1.Column1 = aFullTransform.get(0, 0);
xHomMat.Line1.Column2 = aFullTransform.get(0, 1);
xHomMat.Line1.Column3 = aFullTransform.get(0, 2);
xHomMat.Line1.Column4 = aFullTransform.get(0, 3);
xHomMat.Line2.Column1 = aFullTransform.get(1, 0);
xHomMat.Line2.Column2 = aFullTransform.get(1, 1);
xHomMat.Line2.Column3 = aFullTransform.get(1, 2);
xHomMat.Line2.Column4 = aFullTransform.get(1, 3);
xHomMat.Line3.Column1 = aFullTransform.get(2, 0);
xHomMat.Line3.Column2 = aFullTransform.get(2, 1);
xHomMat.Line3.Column3 = aFullTransform.get(2, 2);
xHomMat.Line3.Column4 = aFullTransform.get(2, 3);
xHomMat.Line4.Column1 = aFullTransform.get(3, 0);
xHomMat.Line4.Column2 = aFullTransform.get(3, 1);
xHomMat.Line4.Column3 = aFullTransform.get(3, 2);
xHomMat.Line4.Column4 = aFullTransform.get(3, 3);
return true;
2000-11-24 16:51:07 +00:00
}
return false;
2000-11-24 16:51:07 +00:00
}
void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
2000-11-24 16:51:07 +00:00
{
rFullTrans.identity();
2000-11-24 16:51:07 +00:00
for(sal_uInt32 a(0L); a < maList.size(); a++)
2000-11-24 16:51:07 +00:00
{
ImpSdXMLExpTransObj3DBase* pObj = maList[a];
2000-11-24 16:51:07 +00:00
switch(pObj->mnType)
{
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
{
rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0);
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
{
rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0);
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
{
rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
{
const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale;
rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
{
const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate;
rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
break;
}
2000-11-24 16:51:07 +00:00
case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
{
rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix;
break;
}
default :
{
DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
break;
}
2000-11-24 16:51:07 +00:00
}
}
}
2000-09-18 16:07:07 +00:00
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH)
: mnX( nX ),
mnY( nY ),
mnW( nW ),
mnH( nH )
{
}
// #100617# Asked vincent hardy: svg:viewBox values may be double precision.
2000-09-18 16:07:07 +00:00
SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
: msString(rNew),
mnX( 0L ),
2000-09-18 16:07:07 +00:00
mnY( 0L ),
mnW( 1000L ),
mnH( 1000L )
2000-09-18 16:07:07 +00:00
{
if(msString.getLength())
{
const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
const sal_Int32 nLen(aStr.getLength());
sal_Int32 nPos(0);
2000-09-18 16:07:07 +00:00
// skip starting spaces
Imp_SkipSpaces(aStr, nPos, nLen);
// get mX, #100617# be prepared for doubles
mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX));
2000-09-18 16:07:07 +00:00
// 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));
2000-09-18 16:07:07 +00:00
// 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));
2000-09-18 16:07:07 +00:00
// 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));
2000-09-18 16:07:07 +00:00
}
}
const OUString& SdXMLImExViewBox::GetExportString()
2000-09-18 16:07:07 +00:00
{
OUString aNewString;
OUString aEmptySpace(sal_Unicode(' '));
2000-09-18 16:07:07 +00:00
Imp_PutNumberChar(aNewString, mnX);
aNewString += aEmptySpace;
2000-09-18 16:07:07 +00:00
Imp_PutNumberChar(aNewString, mnY);
aNewString += aEmptySpace;
2000-09-18 16:07:07 +00:00
Imp_PutNumberChar(aNewString, mnW);
aNewString += aEmptySpace;
2000-09-18 16:07:07 +00:00
Imp_PutNumberChar(aNewString, mnH);
2000-09-18 16:07:07 +00:00
// set new string
msString = aNewString;
2000-09-18 16:07:07 +00:00
return msString;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints,
const SdXMLImExViewBox& rViewBox,
const awt::Point& rObjectPos,
const awt::Size& rObjectSize,
// #96328#
const bool bClosed)
2000-09-18 16:07:07 +00:00
: maPoly( 0L )
{
DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
2000-09-18 16:07:07 +00:00
// 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();
2000-09-18 16:07:07 +00:00
// 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--;
2000-09-18 16:07:07 +00:00
// object size and ViewBox size different?
bool bScale(rObjectSize.Width != rViewBox.GetWidth()
|| rObjectSize.Height != rViewBox.GetHeight());
bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
2000-09-18 16:07:07 +00:00
for(sal_Int32 a(0L); a < nCnt; a++)
2000-09-18 16:07:07 +00:00
{
// prepare coordinates
sal_Int32 nX( pArray->X - rObjectPos.X );
sal_Int32 nY( pArray->Y - rObjectPos.Y );
2000-09-18 16:07:07 +00:00
if(bScale && rObjectSize.Width && rObjectSize.Height)
{
nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width;
nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height;
}
2000-09-18 16:07:07 +00:00
if(bTranslate)
{
nX += rViewBox.GetX();
nY += rViewBox.GetY();
}
2000-09-18 16:07:07 +00:00
// X and comma
Imp_PutNumberChar(aNewString, nX);
aNewString += String(sal_Unicode(','));
2000-09-18 16:07:07 +00:00
// Y and space (not for last)
Imp_PutNumberChar(aNewString, nY);
if(a + 1 != nCnt)
aNewString += String(sal_Unicode(' '));
2000-09-18 16:07:07 +00:00
// next point
pArray++;
}
// set new string
msString = aNewString;
}
2000-09-18 16:07:07 +00:00
}
// #100617# svg:polyline or svg:polygon values may be double precision.
2000-09-18 16:07:07 +00:00
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);
2000-09-18 16:07:07 +00:00
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);
2000-09-18 16:07:07 +00:00
// skip spaces and commas
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// skip number, #100617# be prepared for doubles
Imp_SkipDouble(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
// skip spaces and commas
Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
// one more point
nNumPoints++;
}
// second loop
if(nNumPoints)
{
nPos = 0L;
maPoly.realloc(1L);
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()
2000-09-18 16:07:07 +00:00
|| rObjectSize.Height != rViewBox.GetHeight());
bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
2000-09-18 16:07:07 +00:00
// 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));
2000-09-18 16:07:07 +00:00
// 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));
2000-09-18 16:07:07 +00:00
// 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() )
2000-09-18 16:07:07 +00:00
{
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)
: mrViewBox( rViewBox ),
mbIsClosed( false ),
mbIsCurve( false ),
2000-09-18 16:07:07 +00:00
mnLastX( 0L ),
mnLastY( 0L ),
maPoly( 0L ),
maFlag( 0L )
{
}
void Imp_GetPrevPos(awt::Point*& pPrevPos1,
drawing::PolygonFlags& aPrevFlag1,
const bool bClosed, awt::Point* pPoints,
2000-09-18 16:07:07 +00:00
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)
2000-09-18 16:07:07 +00:00
{
nX = pPointArray->X - rObjectPos.X;
nY = pPointArray->Y - rObjectPos.Y;
if(bScale && rObjectSize.Width && rObjectSize.Height )
2000-09-18 16:07:07 +00:00
{
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
2000-09-18 16:07:07 +00:00
void SdXMLImExSvgDElement::AddPolygon(
drawing::PointSequence* pPoints,
drawing::FlagSequence* pFlags,
const awt::Point& rObjectPos,
const awt::Size& rObjectSize,
bool bClosed, bool bRelative)
2000-09-18 16:07:07 +00:00
{
DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)");
2000-09-18 16:07:07 +00:00
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;
}
}
2000-09-18 16:07:07 +00:00
// 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;
if((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--;
}
}
2000-09-18 16:07:07 +00:00
// bezier poly, handle curves
bool bDidWriteStart(false);
2000-09-18 16:07:07 +00:00
for(sal_Int32 a(0L); a < nCnt; a++)
2000-09-18 16:07:07 +00:00
{
if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray)
2000-09-18 16:07:07 +00:00
{
bool bDidWriteAsCurve(false);
2000-09-18 16:07:07 +00:00
if(bDidWriteStart)
{
if(pFlags)
2000-09-18 16:07:07 +00:00
{
// real curve point, get previous to see if it's a control point
awt::Point* pPrevPos1;
drawing::PolygonFlags aPrevFlag1;
2000-09-18 16:07:07 +00:00
Imp_GetPrevPos(pPrevPos1, aPrevFlag1, bClosed, pPoints->getArray(),
pFlags->getArray(), a, nCnt, 1);
2000-09-18 16:07:07 +00:00
if(pPrevPos1 && drawing::PolygonFlags_CONTROL == aPrevFlag1)
2000-09-18 16:07:07 +00:00
{
// get previous2 to see if it's a control point, too
awt::Point* pPrevPos2;
drawing::PolygonFlags aPrevFlag2;
2000-09-18 16:07:07 +00:00
Imp_GetPrevPos(pPrevPos2, aPrevFlag2, bClosed, pPoints->getArray(),
pFlags->getArray(), a, nCnt, 2);
2000-09-18 16:07:07 +00:00
if(pPrevPos2 && drawing::PolygonFlags_CONTROL == aPrevFlag2)
2000-09-18 16:07:07 +00:00
{
// 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;
2000-09-18 16:07:07 +00:00
Imp_GetPrevPos(pPrevPos3, aPrevFlag3, bClosed, pPoints->getArray(),
pFlags->getArray(), a, nCnt, 3);
2000-09-18 16:07:07 +00:00
if(pPrevPos3)
{
// prepare coordinates
sal_Int32 nX, nY;
2000-09-18 16:07:07 +00:00
Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
mrViewBox, bScale, bTranslate);
2000-09-18 16:07:07 +00:00
// #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;
}
}
2000-09-18 16:07:07 +00:00
#ifdef TEST_QUADRATIC_CURVES
if(bDoTestHere)
2000-09-18 16:07:07 +00:00
{
bIsQuadratic = false;
2000-09-18 16:07:07 +00:00
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;
}
}
2000-09-18 16:07:07 +00:00
if(bPrevPointIsSymmetric)
{
// write a shorthand/smooth quadratic curveto entry (T)
if(bRelative)
{
if(aLastCommand != sal_Unicode('t'))
aNewString += OUString(sal_Unicode('t'));
Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
aLastCommand = sal_Unicode('t');
}
else
{
if(aLastCommand != sal_Unicode('T'))
aNewString += OUString(sal_Unicode('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(bRelative)
{
if(aLastCommand != sal_Unicode('q'))
aNewString += OUString(sal_Unicode('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 += OUString(sal_Unicode('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(bRelative)
{
if(aLastCommand != sal_Unicode('t'))
aNewString += String(sal_Unicode('t'));
Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
aLastCommand = sal_Unicode('t');
}
else
{
if(aLastCommand != sal_Unicode('T'))
aNewString += String(sal_Unicode('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(bRelative)
{
if(aLastCommand != sal_Unicode('q'))
aNewString += String(sal_Unicode('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 += String(sal_Unicode('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
2000-09-18 16:07:07 +00:00
}
else
{
bool bPrevPointIsSymmetric(false);
2000-09-18 16:07:07 +00:00
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;
}
}
2000-09-18 16:07:07 +00:00
// 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(bRelative)
{
if(aLastCommand != sal_Unicode('s'))
aNewString += String(sal_Unicode('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 += String(sal_Unicode('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(bRelative)
{
if(aLastCommand != sal_Unicode('c'))
aNewString += String(sal_Unicode('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 += String(sal_Unicode('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');
}
}
2000-09-18 16:07:07 +00:00
}
// remember that current point IS written
bDidWriteAsCurve = true;
// remember new last position
mnLastX = nX;
mnLastY = nY;
2000-09-18 16:07:07 +00:00
}
}
}
}
}
if(!bDidWriteAsCurve)
{
// current point not yet written, prepare coordinates
sal_Int32 nX, nY;
2000-09-18 16:07:07 +00:00
Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
mrViewBox, bScale, bTranslate);
2000-09-18 16:07:07 +00:00
if(bDidWriteStart)
2000-09-18 16:07:07 +00:00
{
// write as normal point
if(mnLastX == nX)
2000-09-18 16:07:07 +00:00
{
if(bRelative)
{
if(aLastCommand != sal_Unicode('v'))
aNewString += String(sal_Unicode('v'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('v');
}
else
{
if(aLastCommand != sal_Unicode('V'))
aNewString += String(sal_Unicode('V'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nY);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('V');
}
2000-09-18 16:07:07 +00:00
}
else if(mnLastY == nY)
2000-09-18 16:07:07 +00:00
{
if(bRelative)
{
if(aLastCommand != sal_Unicode('h'))
aNewString += String(sal_Unicode('h'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('h');
}
else
{
if(aLastCommand != sal_Unicode('H'))
aNewString += String(sal_Unicode('H'));
Imp_PutNumberCharWithSpace(aNewString, nX);
aLastCommand = sal_Unicode('H');
}
2000-09-18 16:07:07 +00:00
}
else
{
if(bRelative)
{
if(aLastCommand != sal_Unicode('l'))
aNewString += String(sal_Unicode('l'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
aLastCommand = sal_Unicode('l');
}
else
{
if(aLastCommand != sal_Unicode('L'))
aNewString += String(sal_Unicode('L'));
Imp_PutNumberCharWithSpace(aNewString, nX);
Imp_PutNumberCharWithSpace(aNewString, nY);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('L');
}
2000-09-18 16:07:07 +00:00
}
}
else
{
// write as start point
2000-09-18 16:07:07 +00:00
if(bRelative)
{
aNewString += String(sal_Unicode('m'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('l');
}
else
{
aNewString += String(sal_Unicode('M'));
2000-09-18 16:07:07 +00:00
Imp_PutNumberCharWithSpace(aNewString, nX);
Imp_PutNumberCharWithSpace(aNewString, nY);
2000-09-18 16:07:07 +00:00
aLastCommand = sal_Unicode('L');
}
// remember start written
bDidWriteStart = true;
2000-09-18 16:07:07 +00:00
}
// remember new last position
mnLastX = nX;
mnLastY = nY;
2000-09-18 16:07:07 +00:00
}
}
// next point
pPointArray++;
pFlagArray++;
2000-09-18 16:07:07 +00:00
}
// close path if closed poly
if(bClosed)
{
if(bRelative)
aNewString += String(sal_Unicode('z'));
else
aNewString += String(sal_Unicode('Z'));
}
2000-09-18 16:07:07 +00:00
// append new string
msString += aNewString;
2000-09-18 16:07:07 +00:00
}
}
// #100617# Linear double reader
double Imp_ImportDoubleAndSpaces(
double fRetval, const OUString& rStr, sal_Int32& rPos,
const sal_Int32 nLen, const SvXMLUnitConverter& rConv)
{
fRetval = Imp_GetDoubleChar(rStr, rPos, nLen, rConv, fRetval);
Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
return fRetval;
}
// #100617# Allow to read doubles, too. This will need to be changed to
// the usage of Imp_ImportDoubleAndSpaces(...). For now, this is sufficient
// since the interface cannot transport doubles.
2000-09-18 16:07:07 +00:00
sal_Int32 Imp_ImportNumberAndSpaces(
sal_Int32 nRetval, const OUString& rStr, sal_Int32& rPos,
const sal_Int32 nLen, const SvXMLUnitConverter& rConv)
2000-09-18 16:07:07 +00:00
{
nRetval = FRound(Imp_ImportDoubleAndSpaces(double(nRetval), rStr, rPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
return nRetval;
}
void Imp_PrepareCoorImport(sal_Int32& nX, sal_Int32& nY,
const awt::Point& rObjectPos, const awt::Size& rObjectSize,
const SdXMLImExViewBox& rViewBox, const bool bScale, const bool bTranslate)
2000-09-18 16:07:07 +00:00
{
if(bTranslate)
{
nX -= rViewBox.GetX();
nY -= rViewBox.GetY();
}
if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight())
2000-09-18 16:07:07 +00:00
{
nX = (nX * rObjectSize.Width) / rViewBox.GetWidth();
nY = (nY * rObjectSize.Height) / rViewBox.GetHeight();
}
nX += rObjectPos.X;
nY += rObjectPos.Y;
}
void Imp_AddExportPoints(sal_Int32 nX, sal_Int32 nY,
awt::Point* pPoints, drawing::PolygonFlags* pFlags,
const sal_Int32 nInnerIndex,
drawing::PolygonFlags eFlag)
{
if(pPoints)
pPoints[nInnerIndex] = awt::Point( nX, nY );
if(pFlags)
pFlags[nInnerIndex] = eFlag;
}
void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection)
2000-09-18 16:07:07 +00:00
{
const sal_Int32 nLen1(FRound(aVec1.getLength()));
const sal_Int32 nLen2(FRound(aVec2.getLength()));
aVec1.normalize();
aVec2.normalize();
2000-09-18 16:07:07 +00:00
aVec1 += aVec2;
const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0)));
2000-09-18 16:07:07 +00:00
bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL);
bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL);
}
void Imp_CorrectPolygonFlag(const sal_uInt32 nInnerIndex, const awt::Point* const pInnerSequence,
drawing::PolygonFlags* const pInnerFlags, const sal_Int32 nX1, const sal_Int32 nY1)
{
if(nInnerIndex)
{
const awt::Point aPPrev1 = pInnerSequence[nInnerIndex - 1];
if(nInnerIndex > 1)
{
const awt::Point aPPrev2 = pInnerSequence[nInnerIndex - 2];
const drawing::PolygonFlags aFPrev2 = pInnerFlags[nInnerIndex - 2];
::basegfx::B2DVector aVec1(aPPrev2.X - aPPrev1.X, aPPrev2.Y - aPPrev1.Y);
::basegfx::B2DVector aVec2(nX1 - aPPrev1.X, nY1 - aPPrev1.Y);
bool bSameLength(false);
bool bSameDirection(false);
// get vector values
Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
if(drawing::PolygonFlags_CONTROL == aFPrev2)
{
// point before is a control point
if(bSameDirection)
{
if(bSameLength)
{
// set to PolygonFlags_SYMMETRIC
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC;
}
else
{
// set to PolygonFlags_SMOOTH
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
}
}
else
{
// set to PolygonFlags_NORMAL
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
}
}
else
{
// point before is a simple curve point
if(bSameDirection)
{
// set to PolygonFlags_SMOOTH
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
}
else
{
// set to PolygonFlags_NORMAL
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
}
}
}
else
{
// no point before starpoint, set type to PolygonFlags_NORMAL
pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
}
}
2000-09-18 16:07:07 +00:00
}
SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew,
const SdXMLImExViewBox& rViewBox,
const awt::Point& rObjectPos,
const awt::Size& rObjectSize,
const SvXMLUnitConverter& rConv)
: msString( rNew ),
mrViewBox( rViewBox ),
mbIsClosed( false ),
mbIsCurve( false ),
2000-09-18 16:07:07 +00:00
mnLastX( 0L ),
mnLastY( 0L ),
maPoly( 0L ),
maFlag( 0L )
{
// convert string to polygon
const OUString aStr(msString.getStr(), msString.getLength());
const sal_Int32 nLen(aStr.getLength());
sal_Int32 nPos(0);
2000-09-18 16:07:07 +00:00
sal_Int32 nNumPolys(0L);
bool bEllipticalArc(false);
2000-09-18 16:07:07 +00:00
// object size and ViewBox size different?
bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
2000-09-18 16:07:07 +00:00
|| rObjectSize.Height != mrViewBox.GetHeight());
bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
2000-09-18 16:07:07 +00:00
// first loop: count polys and get flags
Imp_SkipSpaces(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
while(nPos < nLen)
{
switch(aStr[nPos++])
2000-09-18 16:07:07 +00:00
{
case 'Z' :
case 'z' :
{
break;
}
case 'M' :
case 'm' :
{
nNumPolys++;
break;
}
case 'S' :
case 's' :
case 'C' :
case 'c' :
case 'Q' :
case 'q' :
case 'T' :
case 't' :
2000-09-18 16:07:07 +00:00
{
mbIsCurve = true;
2000-09-18 16:07:07 +00:00
break;
}
case 'L' :
case 'l' :
case 'H' :
case 'h' :
case 'V' :
case 'v' :
{
// normal, interpreted values. All okay.
break;
}
case 'A' :
case 'a' :
{
// Not yet interpreted value.
bEllipticalArc = true;
2000-09-18 16:07:07 +00:00
break;
}
}
}
DBG_ASSERT(!bEllipticalArc, "XMLIMP: non-interpreted tags in svg:d element!");
2000-09-18 16:07:07 +00:00
if(nNumPolys)
{
// alloc arrays
maPoly.realloc(nNumPolys);
if(IsCurve())
maFlag.realloc(nNumPolys);
// get outer sequences
drawing::PointSequence* pOuterSequence = maPoly.getArray();
drawing::FlagSequence* pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L;
// prepare new loop, count
sal_uInt32 nPointCount(0L);
nPos = 0;
Imp_SkipSpaces(aStr, nPos, nLen);
// #104076# reset closed flag for next to be started polygon
mbIsClosed = false;
2000-09-18 16:07:07 +00:00
while(nPos < nLen)
{
switch(aStr[nPos])
2000-09-18 16:07:07 +00:00
{
case 'z' :
case 'Z' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
// #104076# remember closed state of current polygon
mbIsClosed = true;
2000-09-18 16:07:07 +00:00
break;
}
case 'm' :
case 'M' :
{
// new poly starts, end-process current poly
2000-09-18 16:07:07 +00:00
if(nPointCount)
{
// #104076# If this partial polygon is closed, use one more point
// to represent that
if(mbIsClosed)
{
nPointCount++;
}
2000-09-18 16:07:07 +00:00
pOuterSequence->realloc(nPointCount);
pOuterSequence++;
2000-09-18 16:07:07 +00:00
if(pOuterFlags)
{
pOuterFlags->realloc(nPointCount);
pOuterFlags++;
}
// reset point count for next polygon
2000-09-18 16:07:07 +00:00
nPointCount = 0L;
}
// #104076# reset closed flag for next to be started polygon
mbIsClosed = false;
2000-09-18 16:07:07 +00:00
// NO break, continue in next case
}
case 'L' :
case 'l' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
nPointCount++;
}
break;
}
case 'H' :
case 'h' :
case 'V' :
case 'v' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
nPointCount++;
}
break;
}
case 'S' :
case 's' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
nPointCount += 3;
}
break;
}
case 'C' :
case 'c' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
nPointCount += 3;
}
break;
}
// #100617# quadratic beziers, supported as cubic ones
case 'Q' :
case 'q' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
// use three points since quadratic is imported as cubic
nPointCount += 3;
}
break;
}
// #100617# relative quadratic beziers, supported as cubic ones
case 'T' :
case 't' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
// use three points since quadratic is imported as cubic
nPointCount += 3;
}
break;
}
// #100617# not yet supported: elliptical arc
case 'A' :
case 'a' :
{
DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2000-09-18 16:07:07 +00:00
}
break;
}
default:
{
nPos++;
DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
break;
}
2000-09-18 16:07:07 +00:00
}
}
// alloc last poly (when points used)
if(nPointCount)
{
// #104076# If this partial polygon is closed, use one more point
// to represent that
if(mbIsClosed)
{
nPointCount++;
}
2000-09-18 16:07:07 +00:00
pOuterSequence->realloc(nPointCount);
pOuterSequence++;
2000-09-18 16:07:07 +00:00
if(pOuterFlags)
{
pOuterFlags->realloc(nPointCount);
pOuterFlags++;
}
}
// set pointers back
pOuterSequence = maPoly.getArray();
pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L;
awt::Point* pNotSoInnerSequence = 0L;
drawing::PolygonFlags* pNotSoInnerFlags = 0L;
2000-09-18 16:07:07 +00:00
sal_uInt32 nInnerIndex(0L);
// prepare new loop, read points
nPos = 0;
Imp_SkipSpaces(aStr, nPos, nLen);
// #104076# reset closed flag for next to be started polygon
mbIsClosed = false;
2000-09-18 16:07:07 +00:00
while(nPos < nLen)
{
bool bRelative(false);
2000-09-18 16:07:07 +00:00
switch(aStr[nPos])
2000-09-18 16:07:07 +00:00
{
case 'z' :
case 'Z' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
// #104076# remember closed state of current polygon
mbIsClosed = true;
2000-11-24 16:51:07 +00:00
// closed: add first point again
// sal_Int32 nX(pInnerSequence[0].X);
// sal_Int32 nY(pInnerSequence[0].Y);
// Imp_AddExportPoints(nX, nY, pInnerSequence, pInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2000-09-18 16:07:07 +00:00
break;
}
case 'm' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'M' :
{
// #104076# end-process current poly
if(mbIsClosed)
{
if(pNotSoInnerSequence)
{
// closed: add first point again
sal_Int32 nX(pNotSoInnerSequence[0].X);
sal_Int32 nY(pNotSoInnerSequence[0].Y);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
}
// reset closed flag for next to be started polygon
mbIsClosed = false;
}
2000-09-18 16:07:07 +00:00
// next poly
pNotSoInnerSequence = pOuterSequence->getArray();
2000-09-18 16:07:07 +00:00
pOuterSequence++;
if(pOuterFlags)
{
pNotSoInnerFlags = pOuterFlags->getArray();
2000-09-18 16:07:07 +00:00
pOuterFlags++;
}
nInnerIndex = 0L;
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
if(bRelative)
{
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform and add point and flag
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2000-09-18 16:07:07 +00:00
}
break;
}
case 'l' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'L' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
if(bRelative)
{
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform and add point and flag
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2000-09-18 16:07:07 +00:00
}
break;
}
case 'h' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'H' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
sal_Int32 nY(mnLastY);
if(bRelative)
nX += mnLastX;
// set last position
mnLastX = nX;
// calc transform and add point and flag
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2000-09-18 16:07:07 +00:00
}
break;
}
case 'v' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'V' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX(mnLastX);
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
if(bRelative)
nY += mnLastY;
// set last position
mnLastY = nY;
// calc transform and add point and flag
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2000-09-18 16:07:07 +00:00
}
break;
}
case 's' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'S' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX1;
sal_Int32 nY1;
sal_Int32 nX2(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY2(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
if(bRelative)
{
nX2 += mnLastX;
nY2 += mnLastY;
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform for new points
Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
// one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
// and the Point X1,Y1 can be constructed by mirroring the point before it.
nX1 = nX2;
nY1 = nY2;
if(nInnerIndex)
{
awt::Point aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1];
2000-09-18 16:07:07 +00:00
if(nInnerIndex > 1)
{
awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2];
2000-09-18 16:07:07 +00:00
nX1 = aPPrev1.X -(aPPrev2.X - aPPrev1.X);
nY1 = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y);
}
// set curve point to symmetric
pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC;
2000-09-18 16:07:07 +00:00
}
// add calculated control point
Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2000-09-18 16:07:07 +00:00
// add new points and set flags
Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2000-09-18 16:07:07 +00:00
}
break;
}
case 'c' :
{
bRelative = true;
2000-09-18 16:07:07 +00:00
}
case 'C' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2000-09-18 16:07:07 +00:00
{
sal_Int32 nX1(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY1(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nX2(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY2(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
2000-09-18 16:07:07 +00:00
if(bRelative)
{
nX1 += mnLastX;
nY1 += mnLastY;
nX2 += mnLastX;
nY2 += mnLastY;
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform for new points
Imp_PrepareCoorImport(nX1, nY1, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
// correct polygon flag for previous point
Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
// add new points and set flags
Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
}
break;
}
// #100617# quadratic beziers are imported as cubic
case 'q' :
{
bRelative = true;
}
case 'Q' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
sal_Int32 nXX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nYY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
if(bRelative)
{
nXX += mnLastX;
nYY += mnLastY;
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform for new points
Imp_PrepareCoorImport(nXX, nYY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
// calculate X1,X2
awt::Point aPPrev1 = (nInnerIndex) ? pNotSoInnerSequence[nInnerIndex-1] : pNotSoInnerSequence[0];
sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0);
sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0);
sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0);
sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0);
// correct polygon flag for previous point
Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
// add new points and set flags
Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
}
break;
}
// #100617# relative quadratic beziers are imported as cubic
case 't' :
{
bRelative = true;
}
case 'T' :
{
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
sal_Int32 nXX;
sal_Int32 nYY;
sal_Int32 nX(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
sal_Int32 nY(Imp_ImportNumberAndSpaces(0L, aStr, nPos, nLen, rConv));
if(bRelative)
{
nX += mnLastX;
nY += mnLastY;
}
// set last position
mnLastX = nX;
mnLastY = nY;
// calc transform for new points
Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
// one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
// and the Point X1,Y1 can be constructed by mirroring the point before it.
nXX = nX;
nYY = nY;
awt::Point aPPrev1 = pNotSoInnerSequence[0];
2000-09-18 16:07:07 +00:00
if(nInnerIndex)
{
aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1];
2000-09-18 16:07:07 +00:00
if(nInnerIndex > 1)
{
awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2];
nXX = aPPrev1.X -(aPPrev2.X - aPPrev1.X);
nYY = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y);
}
2000-09-18 16:07:07 +00:00
// set curve point to smooth here, since length
// is changed and thus only c1 can be used.
pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
}
2000-09-18 16:07:07 +00:00
// calculate X1,X2
sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0);
sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0);
sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0);
sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0);
2000-09-18 16:07:07 +00:00
// correct polygon flag for previous point
Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
2000-09-18 16:07:07 +00:00
// add new points and set flags
Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2000-09-18 16:07:07 +00:00
}
break;
}
// #100617# not yet supported: elliptical arc
case 'A' :
case 'a' :
{
DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
nPos++;
Imp_SkipSpaces(aStr, nPos, nLen);
while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
{
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
}
break;
}
default:
{
nPos++;
DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
break;
}
2000-09-18 16:07:07 +00:00
}
}
// #104076# end-process closed state of last poly
if(mbIsClosed)
{
if(pNotSoInnerSequence)
{
// closed: add first point again
sal_Int32 nX(pNotSoInnerSequence[0].X);
sal_Int32 nY(pNotSoInnerSequence[0].Y);
Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
}
}
// #87202# If it's a curve and it's closed the last point maybe too much
// and just exported since SVG does not allow special handling of same
// start and end point, remove this last point.
// Evtl. correct the last curve flags, too.
if(IsCurve() && IsClosed())
{
// make one more loop over the PolyPolygon
pOuterSequence = maPoly.getArray();
pOuterFlags = maFlag.getArray();
sal_Int32 nOuterCnt(maPoly.getLength());
for(sal_Int32 a(0); a < nOuterCnt; a++)
{
// get Polygon pointers
awt::Point* pInnerSequence = pOuterSequence->getArray();
drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
sal_Int32 nInnerCnt(pOuterSequence->getLength());
while( nInnerCnt >= 2
&& ((pInnerSequence + (nInnerCnt - 2))->X == (pInnerSequence + (nInnerCnt - 1))->X)
&& ((pInnerSequence + (nInnerCnt - 2))->Y == (pInnerSequence + (nInnerCnt - 1))->Y)
&& drawing::PolygonFlags_CONTROL != *(pInnerFlags + (nInnerCnt - 2)))
{
// remove last point from array
pOuterSequence->realloc(nInnerCnt - 1);
pOuterFlags->realloc(nInnerCnt - 1);
// get new pointers
pInnerSequence = pOuterSequence->getArray();
pInnerFlags = pOuterFlags->getArray();
nInnerCnt = pOuterSequence->getLength();
}
// now evtl. correct the last curve flags
if(nInnerCnt >= 4)
{
if( pInnerSequence->X == (pInnerSequence + (nInnerCnt - 1))->X
&& pInnerSequence->Y == (pInnerSequence + (nInnerCnt - 1))->Y
&& drawing::PolygonFlags_CONTROL == *(pInnerFlags + 1)
&& drawing::PolygonFlags_CONTROL == *(pInnerFlags + (nInnerCnt - 2)))
{
awt::Point aPrev = *(pInnerSequence + (nInnerCnt - 2));
awt::Point aCurr = *pInnerSequence;
awt::Point aNext = *(pInnerSequence + 1);
::basegfx::B2DVector aVec1(aPrev.X - aCurr.X, aPrev.Y - aCurr.Y);
::basegfx::B2DVector aVec2(aNext.X - aCurr.X, aNext.Y - aCurr.Y);
bool bSameLength(false);
bool bSameDirection(false);
// get vector values
Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
// set correct flag value
if(bSameDirection)
{
if(bSameLength)
{
// set to PolygonFlags_SYMMETRIC
*pInnerFlags = drawing::PolygonFlags_SYMMETRIC;
*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SYMMETRIC;
}
else
{
// set to PolygonFlags_SMOOTH
*pInnerFlags = drawing::PolygonFlags_SMOOTH;
*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SMOOTH;
}
}
else
{
// set to PolygonFlags_NORMAL
*pInnerFlags = drawing::PolygonFlags_NORMAL;
*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_NORMAL;
}
}
}
// switch to next Polygon
pOuterSequence++;
pOuterFlags++;
}
}
2000-09-18 16:07:07 +00:00
}
}
// eof