xref: /AOO41X/main/xmloff/source/draw/xexptran.cxx (revision 63bba73cc51e0afb45f8a8d578158724bb5afee8)
1*63bba73cSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*63bba73cSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*63bba73cSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*63bba73cSAndrew Rist  * distributed with this work for additional information
6*63bba73cSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*63bba73cSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*63bba73cSAndrew Rist  * "License"); you may not use this file except in compliance
9*63bba73cSAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*63bba73cSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*63bba73cSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*63bba73cSAndrew Rist  * software distributed under the License is distributed on an
15*63bba73cSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*63bba73cSAndrew Rist  * KIND, either express or implied.  See the License for the
17*63bba73cSAndrew Rist  * specific language governing permissions and limitations
18*63bba73cSAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*63bba73cSAndrew Rist  *************************************************************/
21*63bba73cSAndrew Rist 
22*63bba73cSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_xmloff.hxx"
26cdf0e10cSrcweir #include "xexptran.hxx"
27cdf0e10cSrcweir #include <tools/debug.hxx>
28cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
29cdf0e10cSrcweir #include <xmloff/xmluconv.hxx>
30cdf0e10cSrcweir #include <tools/gen.hxx>
31cdf0e10cSrcweir #include <basegfx/vector/b2dvector.hxx>
32cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
33cdf0e10cSrcweir #include <basegfx/tuple/b3dtuple.hxx>
34cdf0e10cSrcweir #include <basegfx/matrix/b3dhommatrix.hxx>
35cdf0e10cSrcweir #include <tools/string.hxx>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir using ::rtl::OUString;
38cdf0e10cSrcweir using ::rtl::OUStringBuffer;
39cdf0e10cSrcweir 
40cdf0e10cSrcweir using namespace ::com::sun::star;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
43cdf0e10cSrcweir // Defines
44cdf0e10cSrcweir 
45cdf0e10cSrcweir #define BORDER_INTEGERS_ARE_EQUAL		(4)
46cdf0e10cSrcweir 
47cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
48cdf0e10cSrcweir // Predeclarations
49cdf0e10cSrcweir 
50cdf0e10cSrcweir void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen);
51cdf0e10cSrcweir void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection);
52cdf0e10cSrcweir 
53cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
54cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
55cdf0e10cSrcweir // parsing help functions for simple chars
56cdf0e10cSrcweir void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
57cdf0e10cSrcweir {
58cdf0e10cSrcweir 	while(rPos < nLen
59cdf0e10cSrcweir 		&& sal_Unicode(' ') == rStr[rPos])
60cdf0e10cSrcweir 		rPos++;
61cdf0e10cSrcweir }
62cdf0e10cSrcweir 
63cdf0e10cSrcweir void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
64cdf0e10cSrcweir {
65cdf0e10cSrcweir 	while(rPos < nLen
66cdf0e10cSrcweir 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos]))
67cdf0e10cSrcweir 		rPos++;
68cdf0e10cSrcweir }
69cdf0e10cSrcweir 
70cdf0e10cSrcweir void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
71cdf0e10cSrcweir {
72cdf0e10cSrcweir 	while(rPos < nLen
73cdf0e10cSrcweir 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos]))
74cdf0e10cSrcweir 		rPos++;
75cdf0e10cSrcweir }
76cdf0e10cSrcweir 
77cdf0e10cSrcweir void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
78cdf0e10cSrcweir {
79cdf0e10cSrcweir 	while(rPos < nLen
80cdf0e10cSrcweir 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos]))
81cdf0e10cSrcweir 		rPos++;
82cdf0e10cSrcweir }
83cdf0e10cSrcweir 
84cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
85cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
86cdf0e10cSrcweir // parsing help functions for integer numbers
87cdf0e10cSrcweir 
88cdf0e10cSrcweir bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
89cdf0e10cSrcweir {
90cdf0e10cSrcweir 	sal_Unicode aChar(rStr[nPos]);
91cdf0e10cSrcweir 
92cdf0e10cSrcweir 	if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
93cdf0e10cSrcweir 		|| (bSignAllowed && sal_Unicode('+') == aChar)
94cdf0e10cSrcweir 		|| (bSignAllowed && sal_Unicode('-') == aChar)
95cdf0e10cSrcweir 	)
96cdf0e10cSrcweir 		return true;
97cdf0e10cSrcweir 	return false;
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos)
101cdf0e10cSrcweir {
102cdf0e10cSrcweir 	sal_Unicode aChar(rStr[nPos]);
103cdf0e10cSrcweir 
104cdf0e10cSrcweir 	if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
105cdf0e10cSrcweir 		|| (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
106cdf0e10cSrcweir 		|| sal_Unicode('%') == aChar
107cdf0e10cSrcweir 	)
108cdf0e10cSrcweir 		return true;
109cdf0e10cSrcweir 	return false;
110cdf0e10cSrcweir }
111cdf0e10cSrcweir 
112cdf0e10cSrcweir void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
113cdf0e10cSrcweir {
114cdf0e10cSrcweir 	bool bSignAllowed(true);
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 	while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed))
117cdf0e10cSrcweir 	{
118cdf0e10cSrcweir 		bSignAllowed = false;
119cdf0e10cSrcweir 		rPos++;
120cdf0e10cSrcweir 	}
121cdf0e10cSrcweir }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
124cdf0e10cSrcweir 	const sal_Int32 nLen)
125cdf0e10cSrcweir {
126cdf0e10cSrcweir 	Imp_SkipNumber(rStr, rPos, nLen);
127cdf0e10cSrcweir 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
130cdf0e10cSrcweir // #100617# Allow to skip doubles, too.
131cdf0e10cSrcweir void Imp_SkipDoubleAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
132cdf0e10cSrcweir 	const sal_Int32 nLen)
133cdf0e10cSrcweir {
134cdf0e10cSrcweir 	Imp_SkipDouble(rStr, rPos, nLen);
135cdf0e10cSrcweir 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
136cdf0e10cSrcweir }
137cdf0e10cSrcweir 
138cdf0e10cSrcweir void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue)
139cdf0e10cSrcweir {
140cdf0e10cSrcweir 	OUStringBuffer sStringBuffer;
141cdf0e10cSrcweir 	SvXMLUnitConverter::convertNumber(sStringBuffer, nValue);
142cdf0e10cSrcweir 	rStr += OUString(sStringBuffer.makeStringAndClear());
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue)
146cdf0e10cSrcweir {
147cdf0e10cSrcweir 	const sal_Int32 aLen(rStr.getLength());
148cdf0e10cSrcweir 	if(aLen)
149cdf0e10cSrcweir 		if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0)
150cdf0e10cSrcweir 			rStr += String(sal_Unicode(' '));
151cdf0e10cSrcweir 	Imp_PutNumberChar(rStr, nValue);
152cdf0e10cSrcweir }
153cdf0e10cSrcweir 
154cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
155cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
156cdf0e10cSrcweir // parsing help functions for double numbers
157cdf0e10cSrcweir 
158cdf0e10cSrcweir void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32)
159cdf0e10cSrcweir {
160cdf0e10cSrcweir 	sal_Unicode aChar(rStr[rPos]);
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 	if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
163cdf0e10cSrcweir 		aChar = rStr[++rPos];
164cdf0e10cSrcweir 
165cdf0e10cSrcweir 	while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
166cdf0e10cSrcweir 		|| sal_Unicode('.') == aChar)
167cdf0e10cSrcweir 	{
168cdf0e10cSrcweir 		aChar = rStr[++rPos];
169cdf0e10cSrcweir 	}
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 	if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
172cdf0e10cSrcweir 	{
173cdf0e10cSrcweir 		aChar = rStr[++rPos];
174cdf0e10cSrcweir 
175cdf0e10cSrcweir 		if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
176cdf0e10cSrcweir 			aChar = rStr[++rPos];
177cdf0e10cSrcweir 
178cdf0e10cSrcweir 		while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
179cdf0e10cSrcweir 		{
180cdf0e10cSrcweir 			aChar = rStr[++rPos];
181cdf0e10cSrcweir 		}
182cdf0e10cSrcweir 	}
183cdf0e10cSrcweir }
184cdf0e10cSrcweir 
185cdf0e10cSrcweir double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen,
186cdf0e10cSrcweir 	const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
187cdf0e10cSrcweir {
188cdf0e10cSrcweir 	sal_Unicode aChar(rStr[rPos]);
189cdf0e10cSrcweir 	OUStringBuffer sNumberString;
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 	if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
192cdf0e10cSrcweir 	{
193cdf0e10cSrcweir 		sNumberString.append(rStr[rPos]);
194cdf0e10cSrcweir 		aChar = rStr[++rPos];
195cdf0e10cSrcweir 	}
196cdf0e10cSrcweir 
197cdf0e10cSrcweir 	while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
198cdf0e10cSrcweir 		|| sal_Unicode('.') == aChar)
199cdf0e10cSrcweir 	{
200cdf0e10cSrcweir 		sNumberString.append(rStr[rPos]);
201cdf0e10cSrcweir 		aChar = rStr[++rPos];
202cdf0e10cSrcweir 	}
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 	if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
205cdf0e10cSrcweir 	{
206cdf0e10cSrcweir 		sNumberString.append(rStr[rPos]);
207cdf0e10cSrcweir 		aChar = rStr[++rPos];
208cdf0e10cSrcweir 
209cdf0e10cSrcweir 		if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
210cdf0e10cSrcweir 		{
211cdf0e10cSrcweir 			sNumberString.append(rStr[rPos]);
212cdf0e10cSrcweir 			aChar = rStr[++rPos];
213cdf0e10cSrcweir 		}
214cdf0e10cSrcweir 
215cdf0e10cSrcweir 		while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
216cdf0e10cSrcweir 		{
217cdf0e10cSrcweir 			sNumberString.append(rStr[rPos]);
218cdf0e10cSrcweir 			aChar = rStr[++rPos];
219cdf0e10cSrcweir 		}
220cdf0e10cSrcweir 	}
221cdf0e10cSrcweir 
222cdf0e10cSrcweir 	if(bLookForUnits)
223cdf0e10cSrcweir 	{
224cdf0e10cSrcweir 		Imp_SkipSpaces(rStr, rPos, nLen);
225cdf0e10cSrcweir 		while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
226cdf0e10cSrcweir 			sNumberString.append(rStr[rPos++]);
227cdf0e10cSrcweir 	}
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 	if(sNumberString.getLength())
230cdf0e10cSrcweir 	{
231cdf0e10cSrcweir 		if(bLookForUnits)
232cdf0e10cSrcweir 			rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true);
233cdf0e10cSrcweir 		else
234cdf0e10cSrcweir 			rConv.convertDouble(fRetval, sNumberString.makeStringAndClear());
235cdf0e10cSrcweir 	}
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 	return fRetval;
238cdf0e10cSrcweir }
239cdf0e10cSrcweir 
240cdf0e10cSrcweir void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
241cdf0e10cSrcweir 	bool bConvertUnits = false)
242cdf0e10cSrcweir {
243cdf0e10cSrcweir 	OUStringBuffer sStringBuffer;
244cdf0e10cSrcweir 
245cdf0e10cSrcweir 	if(bConvertUnits)
246cdf0e10cSrcweir 		rConv.convertDouble(sStringBuffer, fValue, true);
247cdf0e10cSrcweir 	else
248cdf0e10cSrcweir 		rConv.convertDouble(sStringBuffer, fValue);
249cdf0e10cSrcweir 
250cdf0e10cSrcweir 	rStr += OUString(sStringBuffer.makeStringAndClear());
251cdf0e10cSrcweir }
252cdf0e10cSrcweir 
253cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
254cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
255cdf0e10cSrcweir // base class of all 2D transform objects
256cdf0e10cSrcweir 
257cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DBase
258cdf0e10cSrcweir {
259cdf0e10cSrcweir 	sal_uInt16					mnType;
260cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
261cdf0e10cSrcweir 	:	mnType(nType) {}
262cdf0e10cSrcweir };
263cdf0e10cSrcweir 
264cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
265cdf0e10cSrcweir // possible object types for 2D
266cdf0e10cSrcweir 
267cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_ROTATE			0x0000
268cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_SCALE			0x0001
269cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE		0x0002
270cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_SKEWX			0x0003
271cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_SKEWY			0x0004
272cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ2D_MATRIX			0x0005
273cdf0e10cSrcweir 
274cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
275cdf0e10cSrcweir // classes of objects, different sizes
276cdf0e10cSrcweir 
277cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
278cdf0e10cSrcweir {
279cdf0e10cSrcweir 	double						mfRotate;
280cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DRotate(double fVal)
281cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {}
282cdf0e10cSrcweir };
283cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
284cdf0e10cSrcweir {
285cdf0e10cSrcweir 	::basegfx::B2DTuple			maScale;
286cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
287cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {}
288cdf0e10cSrcweir };
289cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
290cdf0e10cSrcweir {
291cdf0e10cSrcweir 	::basegfx::B2DTuple			maTranslate;
292cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
293cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {}
294cdf0e10cSrcweir };
295cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
296cdf0e10cSrcweir {
297cdf0e10cSrcweir 	double						mfSkewX;
298cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DSkewX(double fVal)
299cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {}
300cdf0e10cSrcweir };
301cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
302cdf0e10cSrcweir {
303cdf0e10cSrcweir 	double						mfSkewY;
304cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DSkewY(double fVal)
305cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {}
306cdf0e10cSrcweir };
307cdf0e10cSrcweir struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
308cdf0e10cSrcweir {
309cdf0e10cSrcweir 	::basegfx::B2DHomMatrix		maMatrix;
310cdf0e10cSrcweir 	ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
311cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {}
312cdf0e10cSrcweir };
313cdf0e10cSrcweir 
314cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
315cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
316cdf0e10cSrcweir // delete all entries in list
317cdf0e10cSrcweir 
318cdf0e10cSrcweir void SdXMLImExTransform2D::EmptyList()
319cdf0e10cSrcweir {
320cdf0e10cSrcweir     const sal_uInt32 nCount = maList.size();
321cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
322cdf0e10cSrcweir 	{
323cdf0e10cSrcweir 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 		switch(pObj->mnType)
326cdf0e10cSrcweir 		{
327cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE		:
328cdf0e10cSrcweir 			{
329cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DRotate*)pObj;
330cdf0e10cSrcweir 				break;
331cdf0e10cSrcweir 			}
332cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
333cdf0e10cSrcweir 			{
334cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DScale*)pObj;
335cdf0e10cSrcweir 				break;
336cdf0e10cSrcweir 			}
337cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
338cdf0e10cSrcweir 			{
339cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DTranslate*)pObj;
340cdf0e10cSrcweir 				break;
341cdf0e10cSrcweir 			}
342cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
343cdf0e10cSrcweir 			{
344cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DSkewX*)pObj;
345cdf0e10cSrcweir 				break;
346cdf0e10cSrcweir 			}
347cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
348cdf0e10cSrcweir 			{
349cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DSkewY*)pObj;
350cdf0e10cSrcweir 				break;
351cdf0e10cSrcweir 			}
352cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX		:
353cdf0e10cSrcweir 			{
354cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj2DMatrix*)pObj;
355cdf0e10cSrcweir 				break;
356cdf0e10cSrcweir 			}
357cdf0e10cSrcweir 			default :
358cdf0e10cSrcweir 			{
359cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
360cdf0e10cSrcweir 				break;
361cdf0e10cSrcweir 			}
362cdf0e10cSrcweir 		}
363cdf0e10cSrcweir 	}
364cdf0e10cSrcweir 
365cdf0e10cSrcweir 	maList.clear();
366cdf0e10cSrcweir }
367cdf0e10cSrcweir 
368cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
369cdf0e10cSrcweir // add members
370cdf0e10cSrcweir 
371cdf0e10cSrcweir void SdXMLImExTransform2D::AddRotate(double fNew)
372cdf0e10cSrcweir {
373cdf0e10cSrcweir 	if(fNew != 0.0)
374cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew));
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir void SdXMLImExTransform2D::AddScale(const ::basegfx::B2DTuple& rNew)
378cdf0e10cSrcweir {
379cdf0e10cSrcweir 	if(1.0 != rNew.getX() || 1.0 != rNew.getY())
380cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DScale(rNew));
381cdf0e10cSrcweir }
382cdf0e10cSrcweir 
383cdf0e10cSrcweir void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
384cdf0e10cSrcweir {
385cdf0e10cSrcweir 	if(!rNew.equalZero())
386cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew));
387cdf0e10cSrcweir }
388cdf0e10cSrcweir 
389cdf0e10cSrcweir void SdXMLImExTransform2D::AddSkewX(double fNew)
390cdf0e10cSrcweir {
391cdf0e10cSrcweir 	if(fNew != 0.0)
392cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew));
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
395cdf0e10cSrcweir void SdXMLImExTransform2D::AddSkewY(double fNew)
396cdf0e10cSrcweir {
397cdf0e10cSrcweir 	if(fNew != 0.0)
398cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fNew));
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir void SdXMLImExTransform2D::AddMatrix(const ::basegfx::B2DHomMatrix& rNew)
402cdf0e10cSrcweir {
403cdf0e10cSrcweir 	if(!rNew.isIdentity())
404cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj2DMatrix(rNew));
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
408cdf0e10cSrcweir // gen string for export
409cdf0e10cSrcweir const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv)
410cdf0e10cSrcweir {
411cdf0e10cSrcweir 	OUString aNewString;
412cdf0e10cSrcweir 	OUString aClosingBrace(sal_Unicode(')'));
413cdf0e10cSrcweir 	OUString aEmptySpace(sal_Unicode(' '));
414cdf0e10cSrcweir 
415cdf0e10cSrcweir 	const sal_uInt32 nCount = maList.size();
416cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
417cdf0e10cSrcweir 	{
418cdf0e10cSrcweir 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
419cdf0e10cSrcweir 		switch(pObj->mnType)
420cdf0e10cSrcweir 		{
421cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE	:
422cdf0e10cSrcweir 			{
423cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("rotate (");
424cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate);
425cdf0e10cSrcweir 				aNewString += aClosingBrace;
426cdf0e10cSrcweir 				break;
427cdf0e10cSrcweir 			}
428cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
429cdf0e10cSrcweir 			{
430cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("scale (");
431cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX());
432cdf0e10cSrcweir 				aNewString += aEmptySpace;
433cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY());
434cdf0e10cSrcweir 				aNewString += aClosingBrace;
435cdf0e10cSrcweir 				break;
436cdf0e10cSrcweir 			}
437cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
438cdf0e10cSrcweir 			{
439cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("translate (");
440cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true);
441cdf0e10cSrcweir 				aNewString += aEmptySpace;
442cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true);
443cdf0e10cSrcweir 				aNewString += aClosingBrace;
444cdf0e10cSrcweir 				break;
445cdf0e10cSrcweir 			}
446cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
447cdf0e10cSrcweir 			{
448cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("skewX (");
449cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX);
450cdf0e10cSrcweir 				aNewString += aClosingBrace;
451cdf0e10cSrcweir 				break;
452cdf0e10cSrcweir 			}
453cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
454cdf0e10cSrcweir 			{
455cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("skewY (");
456cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY);
457cdf0e10cSrcweir 				aNewString += aClosingBrace;
458cdf0e10cSrcweir 				break;
459cdf0e10cSrcweir 			}
460cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX	:
461cdf0e10cSrcweir 			{
462cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("matrix (");
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 				// a
465cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0));
466cdf0e10cSrcweir 				aNewString += aEmptySpace;
467cdf0e10cSrcweir 
468cdf0e10cSrcweir 				// b
469cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0));
470cdf0e10cSrcweir 				aNewString += aEmptySpace;
471cdf0e10cSrcweir 
472cdf0e10cSrcweir 				// c
473cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1));
474cdf0e10cSrcweir 				aNewString += aEmptySpace;
475cdf0e10cSrcweir 
476cdf0e10cSrcweir 				// d
477cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1));
478cdf0e10cSrcweir 				aNewString += aEmptySpace;
479cdf0e10cSrcweir 
480cdf0e10cSrcweir 				// e
481cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true);
482cdf0e10cSrcweir 				aNewString += aEmptySpace;
483cdf0e10cSrcweir 
484cdf0e10cSrcweir 				// f
485cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true);
486cdf0e10cSrcweir 
487cdf0e10cSrcweir 				aNewString += aClosingBrace;
488cdf0e10cSrcweir 				break;
489cdf0e10cSrcweir 			}
490cdf0e10cSrcweir 			default :
491cdf0e10cSrcweir 			{
492cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
493cdf0e10cSrcweir 				break;
494cdf0e10cSrcweir 			}
495cdf0e10cSrcweir 		}
496cdf0e10cSrcweir 
497cdf0e10cSrcweir 		// if not the last entry, add one space to next tag
498cdf0e10cSrcweir 		if(a + 1UL != maList.size())
499cdf0e10cSrcweir 		{
500cdf0e10cSrcweir 			aNewString += aEmptySpace;
501cdf0e10cSrcweir 		}
502cdf0e10cSrcweir 	}
503cdf0e10cSrcweir 
504cdf0e10cSrcweir 	// fill string form OUString
505cdf0e10cSrcweir 	msString = aNewString;
506cdf0e10cSrcweir 
507cdf0e10cSrcweir 	return msString;
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
511cdf0e10cSrcweir // for Import: constructor with string, parses it and generates entries
512cdf0e10cSrcweir SdXMLImExTransform2D::SdXMLImExTransform2D(const OUString& rNew, const SvXMLUnitConverter& rConv)
513cdf0e10cSrcweir {
514cdf0e10cSrcweir 	SetString(rNew, rConv);
515cdf0e10cSrcweir }
516cdf0e10cSrcweir 
517cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
518cdf0e10cSrcweir // sets new string, parses it and generates entries
519cdf0e10cSrcweir void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
520cdf0e10cSrcweir {
521cdf0e10cSrcweir 	msString = rNew;
522cdf0e10cSrcweir 	EmptyList();
523cdf0e10cSrcweir 
524cdf0e10cSrcweir 	if(msString.getLength())
525cdf0e10cSrcweir 	{
526cdf0e10cSrcweir 		const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
527cdf0e10cSrcweir 		const sal_Int32 nLen(aStr.getLength());
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 		const OUString aString_rotate(OUString::createFromAscii("rotate"));
530cdf0e10cSrcweir 		const OUString aString_scale(OUString::createFromAscii("scale"));
531cdf0e10cSrcweir 		const OUString aString_translate(OUString::createFromAscii("translate"));
532cdf0e10cSrcweir 		const OUString aString_skewX(OUString::createFromAscii("skewX"));
533cdf0e10cSrcweir 		const OUString aString_skewY(OUString::createFromAscii("skewY"));
534cdf0e10cSrcweir 		const OUString aString_matrix(OUString::createFromAscii("matrix"));
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 		sal_Int32 nPos(0);
537cdf0e10cSrcweir 
538cdf0e10cSrcweir 		while(nPos < nLen)
539cdf0e10cSrcweir 		{
540cdf0e10cSrcweir 			// skip spaces
541cdf0e10cSrcweir 			Imp_SkipSpaces(aStr, nPos, nLen);
542cdf0e10cSrcweir 
543cdf0e10cSrcweir 			// look for tag
544cdf0e10cSrcweir 			if(nPos < nLen)
545cdf0e10cSrcweir 			{
546cdf0e10cSrcweir 				if(nPos == aStr.indexOf(aString_rotate, nPos))
547cdf0e10cSrcweir 				{
548cdf0e10cSrcweir 					double fValue(0.0);
549cdf0e10cSrcweir 					nPos += 6;
550cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
551cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
552cdf0e10cSrcweir 					if(fValue != 0.0)
553cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue));
554cdf0e10cSrcweir 
555cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
556cdf0e10cSrcweir 				}
557cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_scale, nPos))
558cdf0e10cSrcweir 				{
559cdf0e10cSrcweir 					::basegfx::B2DTuple aValue(1.0, 1.0);
560cdf0e10cSrcweir 					nPos += 5;
561cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
562cdf0e10cSrcweir 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
563cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
564cdf0e10cSrcweir 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
565cdf0e10cSrcweir 
566cdf0e10cSrcweir 					if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
567cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue));
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
570cdf0e10cSrcweir 				}
571cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_translate, nPos))
572cdf0e10cSrcweir 				{
573cdf0e10cSrcweir 					::basegfx::B2DTuple aValue;
574cdf0e10cSrcweir 					nPos += 9;
575cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
576cdf0e10cSrcweir 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
577cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
578cdf0e10cSrcweir 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
579cdf0e10cSrcweir 
580cdf0e10cSrcweir 					if(!aValue.equalZero())
581cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue));
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
584cdf0e10cSrcweir 				}
585cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_skewX, nPos))
586cdf0e10cSrcweir 				{
587cdf0e10cSrcweir 					double fValue(0.0);
588cdf0e10cSrcweir 					nPos += 5;
589cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
590cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
591cdf0e10cSrcweir 					if(fValue != 0.0)
592cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue));
593cdf0e10cSrcweir 
594cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
595cdf0e10cSrcweir 				}
596cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_skewY, nPos))
597cdf0e10cSrcweir 				{
598cdf0e10cSrcweir 					double fValue(0.0);
599cdf0e10cSrcweir 					nPos += 5;
600cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
601cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
602cdf0e10cSrcweir 					if(fValue != 0.0)
603cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue));
604cdf0e10cSrcweir 
605cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
606cdf0e10cSrcweir 				}
607cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_matrix, nPos))
608cdf0e10cSrcweir 				{
609cdf0e10cSrcweir 					::basegfx::B2DHomMatrix aValue;
610cdf0e10cSrcweir 
611cdf0e10cSrcweir 					nPos += 6;
612cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
613cdf0e10cSrcweir 
614cdf0e10cSrcweir 					// a
615cdf0e10cSrcweir 					aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
616cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
617cdf0e10cSrcweir 
618cdf0e10cSrcweir 					// b
619cdf0e10cSrcweir 					aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
620cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
621cdf0e10cSrcweir 
622cdf0e10cSrcweir 					// c
623cdf0e10cSrcweir 					aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
624cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
625cdf0e10cSrcweir 
626cdf0e10cSrcweir 					// d
627cdf0e10cSrcweir 					aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
628cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
629cdf0e10cSrcweir 
630cdf0e10cSrcweir 					// e
631cdf0e10cSrcweir 					aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
632cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 					// f
635cdf0e10cSrcweir 					aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
636cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
637cdf0e10cSrcweir 
638cdf0e10cSrcweir 					if(!aValue.isIdentity())
639cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue));
640cdf0e10cSrcweir 
641cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
642cdf0e10cSrcweir 				}
643cdf0e10cSrcweir 				else
644cdf0e10cSrcweir 				{
645cdf0e10cSrcweir 					nPos++;
646cdf0e10cSrcweir 				}
647cdf0e10cSrcweir 			}
648cdf0e10cSrcweir 		}
649cdf0e10cSrcweir 	}
650cdf0e10cSrcweir }
651cdf0e10cSrcweir 
652cdf0e10cSrcweir void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans)
653cdf0e10cSrcweir {
654cdf0e10cSrcweir 	rFullTrans.identity();
655cdf0e10cSrcweir 
656cdf0e10cSrcweir 	const sal_uInt32 nCount = maList.size();
657cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
658cdf0e10cSrcweir 	{
659cdf0e10cSrcweir 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
660cdf0e10cSrcweir 		switch(pObj->mnType)
661cdf0e10cSrcweir 		{
662cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE		:
663cdf0e10cSrcweir 			{
664cdf0e10cSrcweir                 // #i78696#
665cdf0e10cSrcweir                 // mfRotate is mathematically wrong oriented since we export/import the angle
666cdf0e10cSrcweir                 // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
667cdf0e10cSrcweir                 // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
668cdf0e10cSrcweir                 // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
669cdf0e10cSrcweir                 // to mirror the value here
670cdf0e10cSrcweir 				rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0);
671cdf0e10cSrcweir 				break;
672cdf0e10cSrcweir 			}
673cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
674cdf0e10cSrcweir 			{
675cdf0e10cSrcweir 				const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale;
676cdf0e10cSrcweir 				rFullTrans.scale(rScale.getX(), rScale.getY());
677cdf0e10cSrcweir 				break;
678cdf0e10cSrcweir 			}
679cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
680cdf0e10cSrcweir 			{
681cdf0e10cSrcweir 				const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate;
682cdf0e10cSrcweir 				rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
683cdf0e10cSrcweir 				break;
684cdf0e10cSrcweir 			}
685cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
686cdf0e10cSrcweir 			{
687cdf0e10cSrcweir 				rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX));
688cdf0e10cSrcweir 				break;
689cdf0e10cSrcweir 			}
690cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
691cdf0e10cSrcweir 			{
692cdf0e10cSrcweir 				rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY));
693cdf0e10cSrcweir 				break;
694cdf0e10cSrcweir 			}
695cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX		:
696cdf0e10cSrcweir 			{
697cdf0e10cSrcweir 				rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix;
698cdf0e10cSrcweir 				break;
699cdf0e10cSrcweir 			}
700cdf0e10cSrcweir 			default :
701cdf0e10cSrcweir 			{
702cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
703cdf0e10cSrcweir 				break;
704cdf0e10cSrcweir 			}
705cdf0e10cSrcweir 		}
706cdf0e10cSrcweir 	}
707cdf0e10cSrcweir }
708cdf0e10cSrcweir 
709cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
710cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
711cdf0e10cSrcweir // base class of all 3D transform objects
712cdf0e10cSrcweir 
713cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DBase
714cdf0e10cSrcweir {
715cdf0e10cSrcweir 	sal_uInt16					mnType;
716cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
717cdf0e10cSrcweir 	:	mnType(nType) {}
718cdf0e10cSrcweir };
719cdf0e10cSrcweir 
720cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
721cdf0e10cSrcweir // possible object types for 3D
722cdf0e10cSrcweir 
723cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X		0x0000
724cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y		0x0001
725cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z		0x0002
726cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_SCALE			0x0003
727cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE		0x0004
728cdf0e10cSrcweir #define	IMP_SDXMLEXP_TRANSOBJ3D_MATRIX			0x0005
729cdf0e10cSrcweir 
730cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
731cdf0e10cSrcweir // classes of objects, different sizes
732cdf0e10cSrcweir 
733cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
734cdf0e10cSrcweir {
735cdf0e10cSrcweir 	double						mfRotateX;
736cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DRotateX(double fVal)
737cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {}
738cdf0e10cSrcweir };
739cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
740cdf0e10cSrcweir {
741cdf0e10cSrcweir 	double						mfRotateY;
742cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DRotateY(double fVal)
743cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {}
744cdf0e10cSrcweir };
745cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
746cdf0e10cSrcweir {
747cdf0e10cSrcweir 	double						mfRotateZ;
748cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DRotateZ(double fVal)
749cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {}
750cdf0e10cSrcweir };
751cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
752cdf0e10cSrcweir {
753cdf0e10cSrcweir 	::basegfx::B3DTuple			maScale;
754cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
755cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {}
756cdf0e10cSrcweir };
757cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
758cdf0e10cSrcweir {
759cdf0e10cSrcweir 	::basegfx::B3DTuple			maTranslate;
760cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
761cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {}
762cdf0e10cSrcweir };
763cdf0e10cSrcweir struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
764cdf0e10cSrcweir {
765cdf0e10cSrcweir 	::basegfx::B3DHomMatrix		maMatrix;
766cdf0e10cSrcweir 	ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
767cdf0e10cSrcweir 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {}
768cdf0e10cSrcweir };
769cdf0e10cSrcweir 
770cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
771cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
772cdf0e10cSrcweir // delete all entries in list
773cdf0e10cSrcweir 
774cdf0e10cSrcweir void SdXMLImExTransform3D::EmptyList()
775cdf0e10cSrcweir {
776cdf0e10cSrcweir 	const sal_uInt32 nCount = maList.size();
777cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
778cdf0e10cSrcweir 	{
779cdf0e10cSrcweir 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
780cdf0e10cSrcweir 
781cdf0e10cSrcweir 		switch(pObj->mnType)
782cdf0e10cSrcweir 		{
783cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
784cdf0e10cSrcweir 			{
785cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DRotateX*)pObj;
786cdf0e10cSrcweir 				break;
787cdf0e10cSrcweir 			}
788cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
789cdf0e10cSrcweir 			{
790cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DRotateY*)pObj;
791cdf0e10cSrcweir 				break;
792cdf0e10cSrcweir 			}
793cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
794cdf0e10cSrcweir 			{
795cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DRotateZ*)pObj;
796cdf0e10cSrcweir 				break;
797cdf0e10cSrcweir 			}
798cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
799cdf0e10cSrcweir 			{
800cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DScale*)pObj;
801cdf0e10cSrcweir 				break;
802cdf0e10cSrcweir 			}
803cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
804cdf0e10cSrcweir 			{
805cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DTranslate*)pObj;
806cdf0e10cSrcweir 				break;
807cdf0e10cSrcweir 			}
808cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX		:
809cdf0e10cSrcweir 			{
810cdf0e10cSrcweir 				delete (ImpSdXMLExpTransObj3DMatrix*)pObj;
811cdf0e10cSrcweir 				break;
812cdf0e10cSrcweir 			}
813cdf0e10cSrcweir 			default :
814cdf0e10cSrcweir 			{
815cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
816cdf0e10cSrcweir 				break;
817cdf0e10cSrcweir 			}
818cdf0e10cSrcweir 		}
819cdf0e10cSrcweir 	}
820cdf0e10cSrcweir 
821cdf0e10cSrcweir 	maList.clear();
822cdf0e10cSrcweir }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
825cdf0e10cSrcweir // add members
826cdf0e10cSrcweir 
827cdf0e10cSrcweir void SdXMLImExTransform3D::AddRotateX(double fNew)
828cdf0e10cSrcweir {
829cdf0e10cSrcweir 	if(fNew != 0.0)
830cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fNew));
831cdf0e10cSrcweir }
832cdf0e10cSrcweir 
833cdf0e10cSrcweir void SdXMLImExTransform3D::AddRotateY(double fNew)
834cdf0e10cSrcweir {
835cdf0e10cSrcweir 	if(fNew != 0.0)
836cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fNew));
837cdf0e10cSrcweir }
838cdf0e10cSrcweir 
839cdf0e10cSrcweir void SdXMLImExTransform3D::AddRotateZ(double fNew)
840cdf0e10cSrcweir {
841cdf0e10cSrcweir 	if(fNew != 0.0)
842cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fNew));
843cdf0e10cSrcweir }
844cdf0e10cSrcweir 
845cdf0e10cSrcweir void SdXMLImExTransform3D::AddScale(const ::basegfx::B3DTuple& rNew)
846cdf0e10cSrcweir {
847cdf0e10cSrcweir 	if(1.0 != rNew.getX() || 1.0 != rNew.getY() || 1.0 != rNew.getZ())
848cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DScale(rNew));
849cdf0e10cSrcweir }
850cdf0e10cSrcweir 
851cdf0e10cSrcweir void SdXMLImExTransform3D::AddTranslate(const ::basegfx::B3DTuple& rNew)
852cdf0e10cSrcweir {
853cdf0e10cSrcweir 	if(!rNew.equalZero())
854cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DTranslate(rNew));
855cdf0e10cSrcweir }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
858cdf0e10cSrcweir {
859cdf0e10cSrcweir 	if(!rNew.isIdentity())
860cdf0e10cSrcweir 		maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew));
861cdf0e10cSrcweir }
862cdf0e10cSrcweir 
863cdf0e10cSrcweir void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
864cdf0e10cSrcweir {
865cdf0e10cSrcweir 	::basegfx::B3DHomMatrix aExportMatrix;
866cdf0e10cSrcweir 
867cdf0e10cSrcweir 	aExportMatrix.set(0, 0, xHomMat.Line1.Column1);
868cdf0e10cSrcweir 	aExportMatrix.set(0, 1, xHomMat.Line1.Column2);
869cdf0e10cSrcweir 	aExportMatrix.set(0, 2, xHomMat.Line1.Column3);
870cdf0e10cSrcweir 	aExportMatrix.set(0, 3, xHomMat.Line1.Column4);
871cdf0e10cSrcweir 	aExportMatrix.set(1, 0, xHomMat.Line2.Column1);
872cdf0e10cSrcweir 	aExportMatrix.set(1, 1, xHomMat.Line2.Column2);
873cdf0e10cSrcweir 	aExportMatrix.set(1, 2, xHomMat.Line2.Column3);
874cdf0e10cSrcweir 	aExportMatrix.set(1, 3, xHomMat.Line2.Column4);
875cdf0e10cSrcweir 	aExportMatrix.set(2, 0, xHomMat.Line3.Column1);
876cdf0e10cSrcweir 	aExportMatrix.set(2, 1, xHomMat.Line3.Column2);
877cdf0e10cSrcweir 	aExportMatrix.set(2, 2, xHomMat.Line3.Column3);
878cdf0e10cSrcweir 	aExportMatrix.set(2, 3, xHomMat.Line3.Column4);
879cdf0e10cSrcweir 
880cdf0e10cSrcweir 	AddMatrix(aExportMatrix);
881cdf0e10cSrcweir }
882cdf0e10cSrcweir 
883cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
884cdf0e10cSrcweir // gen string for export
885cdf0e10cSrcweir const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv)
886cdf0e10cSrcweir {
887cdf0e10cSrcweir 	OUString aNewString;
888cdf0e10cSrcweir 	OUString aClosingBrace(sal_Unicode(')'));
889cdf0e10cSrcweir 	OUString aEmptySpace(sal_Unicode(' '));
890cdf0e10cSrcweir 
891cdf0e10cSrcweir 	const sal_uInt32 nCount = maList.size();
892cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
893cdf0e10cSrcweir 	{
894cdf0e10cSrcweir 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
895cdf0e10cSrcweir 		switch(pObj->mnType)
896cdf0e10cSrcweir 		{
897cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
898cdf0e10cSrcweir 			{
899cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("rotatex (");
900cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX);
901cdf0e10cSrcweir 				aNewString += aClosingBrace;
902cdf0e10cSrcweir 				break;
903cdf0e10cSrcweir 			}
904cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
905cdf0e10cSrcweir 			{
906cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("rotatey (");
907cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY);
908cdf0e10cSrcweir 				aNewString += aClosingBrace;
909cdf0e10cSrcweir 				break;
910cdf0e10cSrcweir 			}
911cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
912cdf0e10cSrcweir 			{
913cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("rotatez (");
914cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
915cdf0e10cSrcweir 				aNewString += aClosingBrace;
916cdf0e10cSrcweir 				break;
917cdf0e10cSrcweir 			}
918cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
919cdf0e10cSrcweir 			{
920cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("scale (");
921cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX());
922cdf0e10cSrcweir 				aNewString += aEmptySpace;
923cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY());
924cdf0e10cSrcweir 				aNewString += aEmptySpace;
925cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ());
926cdf0e10cSrcweir 				aNewString += aClosingBrace;
927cdf0e10cSrcweir 				break;
928cdf0e10cSrcweir 			}
929cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
930cdf0e10cSrcweir 			{
931cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("translate (");
932cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true);
933cdf0e10cSrcweir 				aNewString += aEmptySpace;
934cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true);
935cdf0e10cSrcweir 				aNewString += aEmptySpace;
936cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true);
937cdf0e10cSrcweir 				aNewString += aClosingBrace;
938cdf0e10cSrcweir 				break;
939cdf0e10cSrcweir 			}
940cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX	:
941cdf0e10cSrcweir 			{
942cdf0e10cSrcweir 				aNewString += OUString::createFromAscii("matrix (");
943cdf0e10cSrcweir 
944cdf0e10cSrcweir 				// a
945cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0));
946cdf0e10cSrcweir 				aNewString += aEmptySpace;
947cdf0e10cSrcweir 
948cdf0e10cSrcweir 				// b
949cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0));
950cdf0e10cSrcweir 				aNewString += aEmptySpace;
951cdf0e10cSrcweir 
952cdf0e10cSrcweir 				// c
953cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0));
954cdf0e10cSrcweir 				aNewString += aEmptySpace;
955cdf0e10cSrcweir 
956cdf0e10cSrcweir 				// d
957cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1));
958cdf0e10cSrcweir 				aNewString += aEmptySpace;
959cdf0e10cSrcweir 
960cdf0e10cSrcweir 				// e
961cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1));
962cdf0e10cSrcweir 				aNewString += aEmptySpace;
963cdf0e10cSrcweir 
964cdf0e10cSrcweir 				// f
965cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1));
966cdf0e10cSrcweir 				aNewString += aEmptySpace;
967cdf0e10cSrcweir 
968cdf0e10cSrcweir 				// g
969cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2));
970cdf0e10cSrcweir 				aNewString += aEmptySpace;
971cdf0e10cSrcweir 
972cdf0e10cSrcweir 				// h
973cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2));
974cdf0e10cSrcweir 				aNewString += aEmptySpace;
975cdf0e10cSrcweir 
976cdf0e10cSrcweir 				// i
977cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2));
978cdf0e10cSrcweir 				aNewString += aEmptySpace;
979cdf0e10cSrcweir 
980cdf0e10cSrcweir 				// j
981cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true);
982cdf0e10cSrcweir 				aNewString += aEmptySpace;
983cdf0e10cSrcweir 
984cdf0e10cSrcweir 				// k
985cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true);
986cdf0e10cSrcweir 				aNewString += aEmptySpace;
987cdf0e10cSrcweir 
988cdf0e10cSrcweir 				// l
989cdf0e10cSrcweir 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true);
990cdf0e10cSrcweir 
991cdf0e10cSrcweir 				aNewString += aClosingBrace;
992cdf0e10cSrcweir 				break;
993cdf0e10cSrcweir 			}
994cdf0e10cSrcweir 			default :
995cdf0e10cSrcweir 			{
996cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
997cdf0e10cSrcweir 				break;
998cdf0e10cSrcweir 			}
999cdf0e10cSrcweir 		}
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir 		// if not the last entry, add one space to next tag
1002cdf0e10cSrcweir 		if(a + 1UL != maList.size())
1003cdf0e10cSrcweir 		{
1004cdf0e10cSrcweir 			aNewString += aEmptySpace;
1005cdf0e10cSrcweir 		}
1006cdf0e10cSrcweir 	}
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir 	// fill string form OUString
1009cdf0e10cSrcweir 	msString = aNewString;
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir 	return msString;
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1015cdf0e10cSrcweir // for Import: constructor with string, parses it and generates entries
1016cdf0e10cSrcweir SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv)
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir 	SetString(rNew, rConv);
1019cdf0e10cSrcweir }
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1022cdf0e10cSrcweir // sets new string, parses it and generates entries
1023cdf0e10cSrcweir void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
1024cdf0e10cSrcweir {
1025cdf0e10cSrcweir 	msString = rNew;
1026cdf0e10cSrcweir 	EmptyList();
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir 	if(msString.getLength())
1029cdf0e10cSrcweir 	{
1030cdf0e10cSrcweir 		const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1031cdf0e10cSrcweir 		const sal_Int32 nLen(aStr.getLength());
1032cdf0e10cSrcweir 
1033cdf0e10cSrcweir 		const OUString aString_rotatex(OUString::createFromAscii("rotatex"));
1034cdf0e10cSrcweir 		const OUString aString_rotatey(OUString::createFromAscii("rotatey"));
1035cdf0e10cSrcweir 		const OUString aString_rotatez(OUString::createFromAscii("rotatez"));
1036cdf0e10cSrcweir 		const OUString aString_scale(OUString::createFromAscii("scale"));
1037cdf0e10cSrcweir 		const OUString aString_translate(OUString::createFromAscii("translate"));
1038cdf0e10cSrcweir 		const OUString aString_matrix(OUString::createFromAscii("matrix"));
1039cdf0e10cSrcweir 
1040cdf0e10cSrcweir 		sal_Int32 nPos(0);
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir 		while(nPos < nLen)
1043cdf0e10cSrcweir 		{
1044cdf0e10cSrcweir 			// skip spaces
1045cdf0e10cSrcweir 			Imp_SkipSpaces(aStr, nPos, nLen);
1046cdf0e10cSrcweir 
1047cdf0e10cSrcweir 			// look for tag
1048cdf0e10cSrcweir 			if(nPos < nLen)
1049cdf0e10cSrcweir 			{
1050cdf0e10cSrcweir 				if(nPos == aStr.indexOf(aString_rotatex, nPos))
1051cdf0e10cSrcweir 				{
1052cdf0e10cSrcweir 					double fValue(0.0);
1053cdf0e10cSrcweir 
1054cdf0e10cSrcweir 					nPos += 7;
1055cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1056cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1057cdf0e10cSrcweir 					if(fValue != 0.0)
1058cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue));
1059cdf0e10cSrcweir 
1060cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1061cdf0e10cSrcweir 				}
1062cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_rotatey, nPos))
1063cdf0e10cSrcweir 				{
1064cdf0e10cSrcweir 					double fValue(0.0);
1065cdf0e10cSrcweir 
1066cdf0e10cSrcweir 					nPos += 7;
1067cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1068cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1069cdf0e10cSrcweir 					if(fValue != 0.0)
1070cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue));
1071cdf0e10cSrcweir 
1072cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1073cdf0e10cSrcweir 				}
1074cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_rotatez, nPos))
1075cdf0e10cSrcweir 				{
1076cdf0e10cSrcweir 					double fValue(0.0);
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir 					nPos += 7;
1079cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1080cdf0e10cSrcweir 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1081cdf0e10cSrcweir 					if(fValue != 0.0)
1082cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue));
1083cdf0e10cSrcweir 
1084cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1085cdf0e10cSrcweir 				}
1086cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_scale, nPos))
1087cdf0e10cSrcweir 				{
1088cdf0e10cSrcweir 					::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
1089cdf0e10cSrcweir 
1090cdf0e10cSrcweir 					nPos += 5;
1091cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1092cdf0e10cSrcweir 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
1093cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1094cdf0e10cSrcweir 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
1095cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1096cdf0e10cSrcweir 					aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
1097cdf0e10cSrcweir 
1098cdf0e10cSrcweir 					if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
1099cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue));
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1102cdf0e10cSrcweir 				}
1103cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_translate, nPos))
1104cdf0e10cSrcweir 				{
1105cdf0e10cSrcweir 					::basegfx::B3DTuple aValue;
1106cdf0e10cSrcweir 
1107cdf0e10cSrcweir 					nPos += 9;
1108cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1109cdf0e10cSrcweir 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
1110cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1111cdf0e10cSrcweir 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
1112cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1113cdf0e10cSrcweir 					aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
1114cdf0e10cSrcweir 
1115cdf0e10cSrcweir 					if(!aValue.equalZero())
1116cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue));
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1119cdf0e10cSrcweir 				}
1120cdf0e10cSrcweir 				else if(nPos == aStr.indexOf(aString_matrix, nPos))
1121cdf0e10cSrcweir 				{
1122cdf0e10cSrcweir 					::basegfx::B3DHomMatrix aValue;
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir 					nPos += 6;
1125cdf0e10cSrcweir 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1126cdf0e10cSrcweir 
1127cdf0e10cSrcweir 					// a
1128cdf0e10cSrcweir 					aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
1129cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1130cdf0e10cSrcweir 
1131cdf0e10cSrcweir 					// b
1132cdf0e10cSrcweir 					aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
1133cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1134cdf0e10cSrcweir 
1135cdf0e10cSrcweir 					// c
1136cdf0e10cSrcweir 					aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
1137cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1138cdf0e10cSrcweir 
1139cdf0e10cSrcweir 					// d
1140cdf0e10cSrcweir 					aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
1141cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1142cdf0e10cSrcweir 
1143cdf0e10cSrcweir 					// e
1144cdf0e10cSrcweir 					aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
1145cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1146cdf0e10cSrcweir 
1147cdf0e10cSrcweir 					// f
1148cdf0e10cSrcweir 					aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
1149cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1150cdf0e10cSrcweir 
1151cdf0e10cSrcweir 					// g
1152cdf0e10cSrcweir 					aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
1153cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir 					// h
1156cdf0e10cSrcweir 					aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
1157cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1158cdf0e10cSrcweir 
1159cdf0e10cSrcweir 					// i
1160cdf0e10cSrcweir 					aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
1161cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1162cdf0e10cSrcweir 
1163cdf0e10cSrcweir 					// j
1164cdf0e10cSrcweir 					aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
1165cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1166cdf0e10cSrcweir 
1167cdf0e10cSrcweir 					// k
1168cdf0e10cSrcweir 					aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
1169cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1170cdf0e10cSrcweir 
1171cdf0e10cSrcweir 					// l
1172cdf0e10cSrcweir 					aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
1173cdf0e10cSrcweir 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir 					if(!aValue.isIdentity())
1176cdf0e10cSrcweir 						maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue));
1177cdf0e10cSrcweir 
1178cdf0e10cSrcweir 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1179cdf0e10cSrcweir 				}
1180cdf0e10cSrcweir 				else
1181cdf0e10cSrcweir 				{
1182cdf0e10cSrcweir 					nPos++;
1183cdf0e10cSrcweir 				}
1184cdf0e10cSrcweir 			}
1185cdf0e10cSrcweir 		}
1186cdf0e10cSrcweir 	}
1187cdf0e10cSrcweir }
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat)
1190cdf0e10cSrcweir {
1191cdf0e10cSrcweir 	::basegfx::B3DHomMatrix aFullTransform;
1192cdf0e10cSrcweir 	GetFullTransform(aFullTransform);
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir 	if(!aFullTransform.isIdentity())
1195cdf0e10cSrcweir 	{
1196cdf0e10cSrcweir 		xHomMat.Line1.Column1 = aFullTransform.get(0, 0);
1197cdf0e10cSrcweir 		xHomMat.Line1.Column2 = aFullTransform.get(0, 1);
1198cdf0e10cSrcweir 		xHomMat.Line1.Column3 = aFullTransform.get(0, 2);
1199cdf0e10cSrcweir 		xHomMat.Line1.Column4 = aFullTransform.get(0, 3);
1200cdf0e10cSrcweir 
1201cdf0e10cSrcweir 		xHomMat.Line2.Column1 = aFullTransform.get(1, 0);
1202cdf0e10cSrcweir 		xHomMat.Line2.Column2 = aFullTransform.get(1, 1);
1203cdf0e10cSrcweir 		xHomMat.Line2.Column3 = aFullTransform.get(1, 2);
1204cdf0e10cSrcweir 		xHomMat.Line2.Column4 = aFullTransform.get(1, 3);
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir 		xHomMat.Line3.Column1 = aFullTransform.get(2, 0);
1207cdf0e10cSrcweir 		xHomMat.Line3.Column2 = aFullTransform.get(2, 1);
1208cdf0e10cSrcweir 		xHomMat.Line3.Column3 = aFullTransform.get(2, 2);
1209cdf0e10cSrcweir 		xHomMat.Line3.Column4 = aFullTransform.get(2, 3);
1210cdf0e10cSrcweir 
1211cdf0e10cSrcweir 		xHomMat.Line4.Column1 = aFullTransform.get(3, 0);
1212cdf0e10cSrcweir 		xHomMat.Line4.Column2 = aFullTransform.get(3, 1);
1213cdf0e10cSrcweir 		xHomMat.Line4.Column3 = aFullTransform.get(3, 2);
1214cdf0e10cSrcweir 		xHomMat.Line4.Column4 = aFullTransform.get(3, 3);
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir 		return true;
1217cdf0e10cSrcweir 	}
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir 	return false;
1220cdf0e10cSrcweir }
1221cdf0e10cSrcweir 
1222cdf0e10cSrcweir void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
1223cdf0e10cSrcweir {
1224cdf0e10cSrcweir 	rFullTrans.identity();
1225cdf0e10cSrcweir 
1226cdf0e10cSrcweir 	const sal_uInt32 nCount = maList.size();
1227cdf0e10cSrcweir 	for(sal_uInt32 a(0L); a < nCount; a++)
1228cdf0e10cSrcweir 	{
1229cdf0e10cSrcweir 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
1230cdf0e10cSrcweir 		switch(pObj->mnType)
1231cdf0e10cSrcweir 		{
1232cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
1233cdf0e10cSrcweir 			{
1234cdf0e10cSrcweir 				rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0);
1235cdf0e10cSrcweir 				break;
1236cdf0e10cSrcweir 			}
1237cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
1238cdf0e10cSrcweir 			{
1239cdf0e10cSrcweir 				rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0);
1240cdf0e10cSrcweir 				break;
1241cdf0e10cSrcweir 			}
1242cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
1243cdf0e10cSrcweir 			{
1244cdf0e10cSrcweir 				rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
1245cdf0e10cSrcweir 				break;
1246cdf0e10cSrcweir 			}
1247cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
1248cdf0e10cSrcweir 			{
1249cdf0e10cSrcweir 				const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale;
1250cdf0e10cSrcweir 				rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
1251cdf0e10cSrcweir 				break;
1252cdf0e10cSrcweir 			}
1253cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
1254cdf0e10cSrcweir 			{
1255cdf0e10cSrcweir 				const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate;
1256cdf0e10cSrcweir 				rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
1257cdf0e10cSrcweir 				break;
1258cdf0e10cSrcweir 			}
1259cdf0e10cSrcweir 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX		:
1260cdf0e10cSrcweir 			{
1261cdf0e10cSrcweir 				rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix;
1262cdf0e10cSrcweir 				break;
1263cdf0e10cSrcweir 			}
1264cdf0e10cSrcweir 			default :
1265cdf0e10cSrcweir 			{
1266cdf0e10cSrcweir 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
1267cdf0e10cSrcweir 				break;
1268cdf0e10cSrcweir 			}
1269cdf0e10cSrcweir 		}
1270cdf0e10cSrcweir 	}
1271cdf0e10cSrcweir }
1272cdf0e10cSrcweir 
1273cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1274cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1275cdf0e10cSrcweir 
1276cdf0e10cSrcweir SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH)
1277cdf0e10cSrcweir :	mnX( nX ),
1278cdf0e10cSrcweir 	mnY( nY ),
1279cdf0e10cSrcweir 	mnW( nW ),
1280cdf0e10cSrcweir 	mnH( nH )
1281cdf0e10cSrcweir {
1282cdf0e10cSrcweir }
1283cdf0e10cSrcweir 
1284cdf0e10cSrcweir // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
1285cdf0e10cSrcweir SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
1286cdf0e10cSrcweir :	msString(rNew),
1287cdf0e10cSrcweir 	mnX( 0L ),
1288cdf0e10cSrcweir 	mnY( 0L ),
1289cdf0e10cSrcweir 	mnW( 1000L ),
1290cdf0e10cSrcweir 	mnH( 1000L )
1291cdf0e10cSrcweir {
1292cdf0e10cSrcweir 	if(msString.getLength())
1293cdf0e10cSrcweir 	{
1294cdf0e10cSrcweir 		const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1295cdf0e10cSrcweir 		const sal_Int32 nLen(aStr.getLength());
1296cdf0e10cSrcweir 		sal_Int32 nPos(0);
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir 		// skip starting spaces
1299cdf0e10cSrcweir 		Imp_SkipSpaces(aStr, nPos, nLen);
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir 		// get mX, #100617# be prepared for doubles
1302cdf0e10cSrcweir 		mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX));
1303cdf0e10cSrcweir 
1304cdf0e10cSrcweir 		// skip spaces and commas
1305cdf0e10cSrcweir 		Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1306cdf0e10cSrcweir 
1307cdf0e10cSrcweir 		// get mY, #100617# be prepared for doubles
1308cdf0e10cSrcweir 		mnY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnY));
1309cdf0e10cSrcweir 
1310cdf0e10cSrcweir 		// skip spaces and commas
1311cdf0e10cSrcweir 		Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1312cdf0e10cSrcweir 
1313cdf0e10cSrcweir 		// get mW, #100617# be prepared for doubles
1314cdf0e10cSrcweir 		mnW = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnW));
1315cdf0e10cSrcweir 
1316cdf0e10cSrcweir 		// skip spaces and commas
1317cdf0e10cSrcweir 		Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir 		// get mH, #100617# be prepared for doubles
1320cdf0e10cSrcweir 		mnH = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnH));
1321cdf0e10cSrcweir 	}
1322cdf0e10cSrcweir }
1323cdf0e10cSrcweir 
1324cdf0e10cSrcweir const OUString& SdXMLImExViewBox::GetExportString()
1325cdf0e10cSrcweir {
1326cdf0e10cSrcweir 	OUString aNewString;
1327cdf0e10cSrcweir 	OUString aEmptySpace(sal_Unicode(' '));
1328cdf0e10cSrcweir 
1329cdf0e10cSrcweir 	Imp_PutNumberChar(aNewString, mnX);
1330cdf0e10cSrcweir 	aNewString += aEmptySpace;
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 	Imp_PutNumberChar(aNewString, mnY);
1333cdf0e10cSrcweir 	aNewString += aEmptySpace;
1334cdf0e10cSrcweir 
1335cdf0e10cSrcweir 	Imp_PutNumberChar(aNewString, mnW);
1336cdf0e10cSrcweir 	aNewString += aEmptySpace;
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir 	Imp_PutNumberChar(aNewString, mnH);
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir 	// set new string
1341cdf0e10cSrcweir 	msString = aNewString;
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir 	return msString;
1344cdf0e10cSrcweir }
1345cdf0e10cSrcweir 
1346cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1347cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1348cdf0e10cSrcweir 
1349cdf0e10cSrcweir SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints,
1350cdf0e10cSrcweir 	const SdXMLImExViewBox& rViewBox,
1351cdf0e10cSrcweir 	const awt::Point& rObjectPos,
1352cdf0e10cSrcweir 	const awt::Size& rObjectSize,
1353cdf0e10cSrcweir 	// #96328#
1354cdf0e10cSrcweir 	const bool bClosed)
1355cdf0e10cSrcweir :	maPoly( 0L )
1356cdf0e10cSrcweir {
1357cdf0e10cSrcweir 	DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
1358cdf0e10cSrcweir 
1359cdf0e10cSrcweir 	// add polygon to string
1360cdf0e10cSrcweir 	sal_Int32 nCnt(pPoints->getLength());
1361cdf0e10cSrcweir 
1362cdf0e10cSrcweir 	// #104076# Convert to string only when at last one point included
1363cdf0e10cSrcweir 	if(nCnt > 0)
1364cdf0e10cSrcweir 	{
1365cdf0e10cSrcweir 		OUString aNewString;
1366cdf0e10cSrcweir 		awt::Point* pArray = pPoints->getArray();
1367cdf0e10cSrcweir 
1368cdf0e10cSrcweir 		// last point same? Ignore it.
1369cdf0e10cSrcweir 		// #96328# ...but only when polygon is CLOSED
1370cdf0e10cSrcweir 		if(bClosed && (pArray->X == (pArray + (nCnt - 1))->X) && (pArray->Y == (pArray + (nCnt - 1))->Y))
1371cdf0e10cSrcweir 			nCnt--;
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir 		// object size and ViewBox size different?
1374cdf0e10cSrcweir 		bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1375cdf0e10cSrcweir 			|| rObjectSize.Height != rViewBox.GetHeight());
1376cdf0e10cSrcweir 		bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1377cdf0e10cSrcweir 
1378cdf0e10cSrcweir 		for(sal_Int32 a(0L); a < nCnt; a++)
1379cdf0e10cSrcweir 		{
1380cdf0e10cSrcweir 			// prepare coordinates
1381cdf0e10cSrcweir 			sal_Int32 nX( pArray->X - rObjectPos.X );
1382cdf0e10cSrcweir 			sal_Int32 nY( pArray->Y - rObjectPos.Y );
1383cdf0e10cSrcweir 
1384cdf0e10cSrcweir 			if(bScale && rObjectSize.Width && rObjectSize.Height)
1385cdf0e10cSrcweir 			{
1386cdf0e10cSrcweir 				nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width;
1387cdf0e10cSrcweir 				nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height;
1388cdf0e10cSrcweir 			}
1389cdf0e10cSrcweir 
1390cdf0e10cSrcweir 			if(bTranslate)
1391cdf0e10cSrcweir 			{
1392cdf0e10cSrcweir 				nX += rViewBox.GetX();
1393cdf0e10cSrcweir 				nY += rViewBox.GetY();
1394cdf0e10cSrcweir 			}
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir 			// X and comma
1397cdf0e10cSrcweir 			Imp_PutNumberChar(aNewString, nX);
1398cdf0e10cSrcweir 			aNewString += String(sal_Unicode(','));
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir 			// Y and space (not for last)
1401cdf0e10cSrcweir 			Imp_PutNumberChar(aNewString, nY);
1402cdf0e10cSrcweir 			if(a + 1 != nCnt)
1403cdf0e10cSrcweir 				aNewString += String(sal_Unicode(' '));
1404cdf0e10cSrcweir 
1405cdf0e10cSrcweir 			// next point
1406cdf0e10cSrcweir 			pArray++;
1407cdf0e10cSrcweir 		}
1408cdf0e10cSrcweir 
1409cdf0e10cSrcweir 		// set new string
1410cdf0e10cSrcweir 		msString = aNewString;
1411cdf0e10cSrcweir 	}
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir // #100617# svg:polyline or svg:polygon values may be double precision.
1415cdf0e10cSrcweir SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString& rNew,
1416cdf0e10cSrcweir 	const SdXMLImExViewBox& rViewBox,
1417cdf0e10cSrcweir 	const awt::Point& rObjectPos,
1418cdf0e10cSrcweir 	const awt::Size& rObjectSize,
1419cdf0e10cSrcweir 	const SvXMLUnitConverter& rConv)
1420cdf0e10cSrcweir :	msString( rNew ),
1421cdf0e10cSrcweir 	maPoly( 0L )
1422cdf0e10cSrcweir {
1423cdf0e10cSrcweir 	// convert string to polygon
1424cdf0e10cSrcweir 	const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1425cdf0e10cSrcweir 	const sal_Int32 nLen(aStr.getLength());
1426cdf0e10cSrcweir 	sal_Int32 nPos(0);
1427cdf0e10cSrcweir 	sal_Int32 nNumPoints(0L);
1428cdf0e10cSrcweir 
1429cdf0e10cSrcweir 	// skip starting spaces
1430cdf0e10cSrcweir 	Imp_SkipSpaces(aStr, nPos, nLen);
1431cdf0e10cSrcweir 
1432cdf0e10cSrcweir 	// count points in first loop
1433cdf0e10cSrcweir 	while(nPos < nLen)
1434cdf0e10cSrcweir 	{
1435cdf0e10cSrcweir 		// skip number, #100617# be prepared for doubles
1436cdf0e10cSrcweir 		Imp_SkipDouble(aStr, nPos, nLen);
1437cdf0e10cSrcweir 
1438cdf0e10cSrcweir 		// skip spaces and commas
1439cdf0e10cSrcweir 		Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1440cdf0e10cSrcweir 
1441cdf0e10cSrcweir 		// skip number, #100617# be prepared for doubles
1442cdf0e10cSrcweir 		Imp_SkipDouble(aStr, nPos, nLen);
1443cdf0e10cSrcweir 
1444cdf0e10cSrcweir 		// skip spaces and commas
1445cdf0e10cSrcweir 		Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1446cdf0e10cSrcweir 
1447cdf0e10cSrcweir 		// one more point
1448cdf0e10cSrcweir 		nNumPoints++;
1449cdf0e10cSrcweir 	}
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir 	// second loop
1452cdf0e10cSrcweir 	if(nNumPoints)
1453cdf0e10cSrcweir 	{
1454cdf0e10cSrcweir         nPos = 0;
1455cdf0e10cSrcweir         maPoly.realloc(1);
1456cdf0e10cSrcweir 		drawing::PointSequence* pOuterSequence = maPoly.getArray();
1457cdf0e10cSrcweir 		pOuterSequence->realloc(nNumPoints);
1458cdf0e10cSrcweir 		awt::Point* pInnerSequence = pOuterSequence->getArray();
1459cdf0e10cSrcweir 
1460cdf0e10cSrcweir 		// object size and ViewBox size different?
1461cdf0e10cSrcweir 		bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1462cdf0e10cSrcweir 			|| rObjectSize.Height != rViewBox.GetHeight());
1463cdf0e10cSrcweir 		bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir 		// skip starting spaces
1466cdf0e10cSrcweir 		Imp_SkipSpaces(aStr, nPos, nLen);
1467cdf0e10cSrcweir 
1468cdf0e10cSrcweir 		while(nPos < nLen)
1469cdf0e10cSrcweir 		{
1470cdf0e10cSrcweir 			// prepare new parameter pair
1471cdf0e10cSrcweir 			sal_Int32 nX(0L);
1472cdf0e10cSrcweir 			sal_Int32 nY(0L);
1473cdf0e10cSrcweir 
1474cdf0e10cSrcweir 			// get mX, #100617# be prepared for doubles
1475cdf0e10cSrcweir 			nX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nX));
1476cdf0e10cSrcweir 
1477cdf0e10cSrcweir 			// skip spaces and commas
1478cdf0e10cSrcweir 			Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1479cdf0e10cSrcweir 
1480cdf0e10cSrcweir 			// get mY, #100617# be prepared for doubles
1481cdf0e10cSrcweir 			nY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nY));
1482cdf0e10cSrcweir 
1483cdf0e10cSrcweir 			// skip spaces and commas
1484cdf0e10cSrcweir 			Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1485cdf0e10cSrcweir 
1486cdf0e10cSrcweir 			// prepare parameters
1487cdf0e10cSrcweir 			if(bTranslate)
1488cdf0e10cSrcweir 			{
1489cdf0e10cSrcweir 				nX -= rViewBox.GetX();
1490cdf0e10cSrcweir 				nY -= rViewBox.GetY();
1491cdf0e10cSrcweir 			}
1492cdf0e10cSrcweir 
1493cdf0e10cSrcweir 			if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight() )
1494cdf0e10cSrcweir 			{
1495cdf0e10cSrcweir 				nX = (nX * rObjectSize.Width) / rViewBox.GetWidth();
1496cdf0e10cSrcweir 				nY = (nY * rObjectSize.Height) / rViewBox.GetHeight();
1497cdf0e10cSrcweir 			}
1498cdf0e10cSrcweir 
1499cdf0e10cSrcweir 			nX += rObjectPos.X;
1500cdf0e10cSrcweir 			nY += rObjectPos.Y;
1501cdf0e10cSrcweir 
1502cdf0e10cSrcweir 			// add new point
1503cdf0e10cSrcweir 			*pInnerSequence = awt::Point( nX, nY );
1504cdf0e10cSrcweir 			pInnerSequence++;
1505cdf0e10cSrcweir 		}
1506cdf0e10cSrcweir 	}
1507cdf0e10cSrcweir }
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1510cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
1511cdf0e10cSrcweir 
1512cdf0e10cSrcweir SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox)
1513cdf0e10cSrcweir :	mrViewBox( rViewBox ),
1514cdf0e10cSrcweir 	mbIsClosed( false ),
1515cdf0e10cSrcweir 	mbIsCurve( false ),
1516cdf0e10cSrcweir 	mnLastX( 0L ),
1517cdf0e10cSrcweir 	mnLastY( 0L ),
1518cdf0e10cSrcweir 	maPoly( 0L ),
1519cdf0e10cSrcweir 	maFlag( 0L )
1520cdf0e10cSrcweir {
1521cdf0e10cSrcweir }
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir void Imp_GetPrevPos(awt::Point*& pPrevPos1,
1524cdf0e10cSrcweir 	drawing::PolygonFlags& aPrevFlag1,
1525cdf0e10cSrcweir 	const bool bClosed, awt::Point* pPoints,
1526cdf0e10cSrcweir 	drawing::PolygonFlags* pFlags, const sal_Int32 nPos,
1527cdf0e10cSrcweir 	const sal_Int32 nCnt, const sal_Int32 nAdd)
1528cdf0e10cSrcweir {
1529cdf0e10cSrcweir 	if(bClosed)
1530cdf0e10cSrcweir 	{
1531cdf0e10cSrcweir 		pPrevPos1 = pPoints + ((nPos + nCnt - nAdd) % nCnt);
1532cdf0e10cSrcweir 		aPrevFlag1 = *(pFlags + ((nPos + nCnt - nAdd) % nCnt));
1533cdf0e10cSrcweir 	}
1534cdf0e10cSrcweir 	else if(nPos > (nAdd - 1))
1535cdf0e10cSrcweir 	{
1536cdf0e10cSrcweir 		pPrevPos1 = pPoints + (nPos - nAdd);
1537cdf0e10cSrcweir 		aPrevFlag1 = *(pFlags + (nPos - nAdd));
1538cdf0e10cSrcweir 	}
1539cdf0e10cSrcweir 	else
1540cdf0e10cSrcweir 		pPrevPos1 = 0L;
1541cdf0e10cSrcweir }
1542cdf0e10cSrcweir 
1543cdf0e10cSrcweir void Imp_PrepareCoorExport(sal_Int32& nX, sal_Int32& nY,
1544cdf0e10cSrcweir 	const awt::Point* pPointArray, const awt::Point& rObjectPos,
1545cdf0e10cSrcweir 	const awt::Size& rObjectSize, const SdXMLImExViewBox& mrViewBox,
1546cdf0e10cSrcweir 	const bool bScale, const bool bTranslate)
1547cdf0e10cSrcweir {
1548cdf0e10cSrcweir 	nX = pPointArray->X - rObjectPos.X;
1549cdf0e10cSrcweir 	nY = pPointArray->Y - rObjectPos.Y;
1550cdf0e10cSrcweir 
1551cdf0e10cSrcweir 	if(bScale && rObjectSize.Width && rObjectSize.Height )
1552cdf0e10cSrcweir 	{
1553cdf0e10cSrcweir 		nX = (nX * mrViewBox.GetWidth()) / rObjectSize.Width;
1554cdf0e10cSrcweir 		nY = (nY * mrViewBox.GetHeight()) / rObjectSize.Height;
1555cdf0e10cSrcweir 	}
1556cdf0e10cSrcweir 
1557cdf0e10cSrcweir 	if(bTranslate)
1558cdf0e10cSrcweir 	{
1559cdf0e10cSrcweir 		nX += mrViewBox.GetX();
1560cdf0e10cSrcweir 		nY += mrViewBox.GetY();
1561cdf0e10cSrcweir 	}
1562cdf0e10cSrcweir }
1563cdf0e10cSrcweir 
1564cdf0e10cSrcweir //#define TEST_QUADRATIC_CURVES
1565cdf0e10cSrcweir #ifdef TEST_QUADRATIC_CURVES
1566cdf0e10cSrcweir // To be able to test quadratic curve code: The code concerning to
1567cdf0e10cSrcweir // bDoTestHere can be used (see below). Construct shapes which have their control
1568cdf0e10cSrcweir // points on equal coordinates. When these are written, they can be
1569cdf0e10cSrcweir // forced to create correct 'Q' and 'T' statements using this flag.
1570cdf0e10cSrcweir // These may then be tested for import/exporting.
1571cdf0e10cSrcweir static bool bDoTestHere(true);
1572cdf0e10cSrcweir #endif // TEST_QUADRATIC_CURVES
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir void SdXMLImExSvgDElement::AddPolygon(
1575cdf0e10cSrcweir 	drawing::PointSequence* pPoints,
1576cdf0e10cSrcweir 	drawing::FlagSequence* pFlags,
1577cdf0e10cSrcweir 	const awt::Point& rObjectPos,
1578cdf0e10cSrcweir 	const awt::Size& rObjectSize,
1579cdf0e10cSrcweir 	bool bClosed, bool bRelative)
1580cdf0e10cSrcweir {
1581cdf0e10cSrcweir 	DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)");
1582cdf0e10cSrcweir 
1583cdf0e10cSrcweir 	sal_Int32 nCnt(pPoints->getLength());
1584cdf0e10cSrcweir 
1585cdf0e10cSrcweir 	// #104076# Convert to string only when at last one point included
1586cdf0e10cSrcweir 	if(nCnt > 0)
1587cdf0e10cSrcweir 	{
1588cdf0e10cSrcweir 		// append polygon to string
1589cdf0e10cSrcweir 		OUString aNewString;
1590cdf0e10cSrcweir 		sal_Unicode aLastCommand = ' ';
1591cdf0e10cSrcweir 		awt::Point* pPointArray = pPoints->getArray();
1592cdf0e10cSrcweir 
1593cdf0e10cSrcweir 		// are the flags used at all? If not forget about them
1594cdf0e10cSrcweir 		if(pFlags)
1595cdf0e10cSrcweir 		{
1596cdf0e10cSrcweir 			sal_Int32 nFlagCnt(pFlags->getLength());
1597cdf0e10cSrcweir 
1598cdf0e10cSrcweir 			if(nFlagCnt)
1599cdf0e10cSrcweir 			{
1600cdf0e10cSrcweir 				bool bFlagsUsed(false);
1601cdf0e10cSrcweir 				drawing::PolygonFlags* pFlagArray = pFlags->getArray();
1602cdf0e10cSrcweir 
1603cdf0e10cSrcweir 				for(sal_Int32 a(0); !bFlagsUsed && a < nFlagCnt; a++)
1604cdf0e10cSrcweir 					if(drawing::PolygonFlags_NORMAL != *pFlagArray++)
1605cdf0e10cSrcweir 						bFlagsUsed = true;
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 				if(!bFlagsUsed)
1608cdf0e10cSrcweir 					pFlags = 0L;
1609cdf0e10cSrcweir 			}
1610cdf0e10cSrcweir 			else
1611cdf0e10cSrcweir 			{
1612cdf0e10cSrcweir 				pFlags = 0L;
1613cdf0e10cSrcweir 			}
1614cdf0e10cSrcweir 		}
1615cdf0e10cSrcweir 
1616cdf0e10cSrcweir 		// object size and ViewBox size different?
1617cdf0e10cSrcweir 		bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
1618cdf0e10cSrcweir 			|| rObjectSize.Height != mrViewBox.GetHeight());
1619cdf0e10cSrcweir 		bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
1620cdf0e10cSrcweir 
1621cdf0e10cSrcweir 		// #87202# rework of point reduction:
1622cdf0e10cSrcweir 		// Test for Last point same -> closed, ignore last point. Take
1623cdf0e10cSrcweir 		// some more circumstances in account when looking at curve segments.
1624cdf0e10cSrcweir 		drawing::PolygonFlags* pFlagArray = (pFlags) ? pFlags->getArray() : 0L;
1625cdf0e10cSrcweir 		if((pPointArray->X == (pPointArray + (nCnt - 1))->X) && (pPointArray->Y == (pPointArray + (nCnt - 1))->Y))
1626cdf0e10cSrcweir 		{
1627cdf0e10cSrcweir 			if(pFlags)
1628cdf0e10cSrcweir 			{
1629cdf0e10cSrcweir 				// point needs to be ignored if point before it is
1630cdf0e10cSrcweir 				// NO control point. Else the last point is needed
1631cdf0e10cSrcweir 				// for exporting the last segment of the curve. That means
1632cdf0e10cSrcweir 				// that the last and the first point will be saved double,
1633cdf0e10cSrcweir 				// but SVG does not support a better solution here.
1634cdf0e10cSrcweir 				if(nCnt >= 2 && drawing::PolygonFlags_CONTROL != *(pFlagArray + (nCnt - 2)))
1635cdf0e10cSrcweir 				{
1636cdf0e10cSrcweir 					nCnt--;
1637cdf0e10cSrcweir 				}
1638cdf0e10cSrcweir 			}
1639cdf0e10cSrcweir 			else
1640cdf0e10cSrcweir 			{
1641cdf0e10cSrcweir 				// no curve, ignore last point
1642cdf0e10cSrcweir 				nCnt--;
1643cdf0e10cSrcweir 			}
1644cdf0e10cSrcweir 		}
1645cdf0e10cSrcweir 
1646cdf0e10cSrcweir 		// bezier poly, handle curves
1647cdf0e10cSrcweir 		bool  bDidWriteStart(false);
1648cdf0e10cSrcweir 
1649cdf0e10cSrcweir 		for(sal_Int32 a(0L); a < nCnt; a++)
1650cdf0e10cSrcweir 		{
1651cdf0e10cSrcweir 			if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray)
1652cdf0e10cSrcweir 			{
1653cdf0e10cSrcweir 				bool bDidWriteAsCurve(false);
1654cdf0e10cSrcweir 
1655cdf0e10cSrcweir 				if(bDidWriteStart)
1656cdf0e10cSrcweir 				{
1657cdf0e10cSrcweir 					if(pFlags)
1658cdf0e10cSrcweir 					{
1659cdf0e10cSrcweir 						// real curve point, get previous to see if it's a control point
1660cdf0e10cSrcweir 						awt::Point* pPrevPos1;
1661cdf0e10cSrcweir 						drawing::PolygonFlags aPrevFlag1;
1662cdf0e10cSrcweir 
1663cdf0e10cSrcweir 						Imp_GetPrevPos(pPrevPos1, aPrevFlag1, bClosed, pPoints->getArray(),
1664cdf0e10cSrcweir 							pFlags->getArray(), a, nCnt, 1);
1665cdf0e10cSrcweir 
1666cdf0e10cSrcweir 						if(pPrevPos1 && drawing::PolygonFlags_CONTROL == aPrevFlag1)
1667cdf0e10cSrcweir 						{
1668cdf0e10cSrcweir 							// get previous2 to see if it's a control point, too
1669cdf0e10cSrcweir 							awt::Point* pPrevPos2;
1670cdf0e10cSrcweir 							drawing::PolygonFlags aPrevFlag2;
1671cdf0e10cSrcweir 
1672cdf0e10cSrcweir 							Imp_GetPrevPos(pPrevPos2, aPrevFlag2, bClosed, pPoints->getArray(),
1673cdf0e10cSrcweir 								pFlags->getArray(), a, nCnt, 2);
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir 							if(pPrevPos2 && drawing::PolygonFlags_CONTROL == aPrevFlag2)
1676cdf0e10cSrcweir 							{
1677cdf0e10cSrcweir 								// get previous3 to see if it's a curve point and if,
1678cdf0e10cSrcweir 								// if it is fully symmetric or not
1679cdf0e10cSrcweir 								awt::Point* pPrevPos3;
1680cdf0e10cSrcweir 								drawing::PolygonFlags aPrevFlag3;
1681cdf0e10cSrcweir 
1682cdf0e10cSrcweir 								Imp_GetPrevPos(pPrevPos3, aPrevFlag3, bClosed, pPoints->getArray(),
1683cdf0e10cSrcweir 									pFlags->getArray(), a, nCnt, 3);
1684cdf0e10cSrcweir 
1685cdf0e10cSrcweir 								if(pPrevPos3)
1686cdf0e10cSrcweir 								{
1687cdf0e10cSrcweir 									// prepare coordinates
1688cdf0e10cSrcweir 									sal_Int32 nX, nY;
1689cdf0e10cSrcweir 
1690cdf0e10cSrcweir 									Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
1691cdf0e10cSrcweir 										mrViewBox, bScale, bTranslate);
1692cdf0e10cSrcweir 
1693cdf0e10cSrcweir 									// #100617# test if this curve segment may be written as
1694cdf0e10cSrcweir 									// a quadratic bezier
1695cdf0e10cSrcweir 									// That's the case if both control points are in the same place
1696cdf0e10cSrcweir 									// when they are prolonged to the common quadratic control point
1697cdf0e10cSrcweir 									// Left:  P = (3P1 - P0) / 2
1698cdf0e10cSrcweir 									// Right: P = (3P2 - P3) / 2
1699cdf0e10cSrcweir 									bool bIsQuadratic(false);
1700cdf0e10cSrcweir 									const bool bEnableSaveQuadratic(false);
1701cdf0e10cSrcweir 
1702cdf0e10cSrcweir 									sal_Int32 nPX_L(FRound((double)((3 * pPrevPos2->X) - pPrevPos3->X) / 2.0));
1703cdf0e10cSrcweir 									sal_Int32 nPY_L(FRound((double)((3 * pPrevPos2->Y) - pPrevPos3->Y) / 2.0));
1704cdf0e10cSrcweir 									sal_Int32 nPX_R(FRound((double)((3 * pPrevPos1->X) - pPointArray->X) / 2.0));
1705cdf0e10cSrcweir 									sal_Int32 nPY_R(FRound((double)((3 * pPrevPos1->Y) - pPointArray->Y) / 2.0));
1706cdf0e10cSrcweir 									sal_Int32 nDist(0);
1707cdf0e10cSrcweir 
1708cdf0e10cSrcweir 									if(nPX_L != nPX_R)
1709cdf0e10cSrcweir 									{
1710cdf0e10cSrcweir 										nDist += abs(nPX_L - nPX_R);
1711cdf0e10cSrcweir 									}
1712cdf0e10cSrcweir 
1713cdf0e10cSrcweir 									if(nPY_L != nPY_R)
1714cdf0e10cSrcweir 									{
1715cdf0e10cSrcweir 										nDist += abs(nPY_L - nPY_R);
1716cdf0e10cSrcweir 									}
1717cdf0e10cSrcweir 
1718cdf0e10cSrcweir 									if(nDist <= BORDER_INTEGERS_ARE_EQUAL)
1719cdf0e10cSrcweir 									{
1720cdf0e10cSrcweir 										if(bEnableSaveQuadratic)
1721cdf0e10cSrcweir 										{
1722cdf0e10cSrcweir 											bIsQuadratic = true;
1723cdf0e10cSrcweir 										}
1724cdf0e10cSrcweir 									}
1725cdf0e10cSrcweir 
1726cdf0e10cSrcweir #ifdef TEST_QUADRATIC_CURVES
1727cdf0e10cSrcweir 									if(bDoTestHere)
1728cdf0e10cSrcweir 									{
1729cdf0e10cSrcweir 										bIsQuadratic = false;
1730cdf0e10cSrcweir 
1731cdf0e10cSrcweir 										if(pPrevPos1->X == pPrevPos2->X && pPrevPos1->Y == pPrevPos2->Y)
1732cdf0e10cSrcweir 											bIsQuadratic = true;
1733cdf0e10cSrcweir 									}
1734cdf0e10cSrcweir #endif // TEST_QUADRATIC_CURVES
1735cdf0e10cSrcweir 
1736cdf0e10cSrcweir 									if(bIsQuadratic)
1737cdf0e10cSrcweir 									{
1738cdf0e10cSrcweir #ifdef TEST_QUADRATIC_CURVES
1739cdf0e10cSrcweir 										if(bDoTestHere)
1740cdf0e10cSrcweir 										{
1741cdf0e10cSrcweir 											bool bPrevPointIsSymmetric(false);
1742cdf0e10cSrcweir 
1743cdf0e10cSrcweir 											if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
1744cdf0e10cSrcweir 											{
1745cdf0e10cSrcweir 												// get previous4 to see if it's a control point
1746cdf0e10cSrcweir 												awt::Point* pPrevPos4;
1747cdf0e10cSrcweir 												drawing::PolygonFlags aPrevFlag4;
1748cdf0e10cSrcweir 
1749cdf0e10cSrcweir 												Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1750cdf0e10cSrcweir 													pFlags->getArray(), a, nCnt, 4);
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir 												if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1753cdf0e10cSrcweir 												{
1754cdf0e10cSrcweir 													// okay, prevPos3 is symmetric (c2) and prevPos4
1755cdf0e10cSrcweir 													// is existing control point, the 's' statement can be used
1756cdf0e10cSrcweir 													bPrevPointIsSymmetric = true;
1757cdf0e10cSrcweir 												}
1758cdf0e10cSrcweir 											}
1759cdf0e10cSrcweir 
1760cdf0e10cSrcweir 											if(bPrevPointIsSymmetric)
1761cdf0e10cSrcweir 											{
1762cdf0e10cSrcweir 												// write a shorthand/smooth quadratic curveto entry (T)
1763cdf0e10cSrcweir 												if(bRelative)
1764cdf0e10cSrcweir 												{
1765cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('t'))
1766cdf0e10cSrcweir 														aNewString += OUString(sal_Unicode('t'));
1767cdf0e10cSrcweir 
1768cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1769cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1770cdf0e10cSrcweir 
1771cdf0e10cSrcweir 													aLastCommand = sal_Unicode('t');
1772cdf0e10cSrcweir 												}
1773cdf0e10cSrcweir 												else
1774cdf0e10cSrcweir 												{
1775cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('T'))
1776cdf0e10cSrcweir 														aNewString += OUString(sal_Unicode('T'));
1777cdf0e10cSrcweir 
1778cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX);
1779cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY);
1780cdf0e10cSrcweir 
1781cdf0e10cSrcweir 													aLastCommand = sal_Unicode('T');
1782cdf0e10cSrcweir 												}
1783cdf0e10cSrcweir 											}
1784cdf0e10cSrcweir 											else
1785cdf0e10cSrcweir 											{
1786cdf0e10cSrcweir 												// prepare coordinates
1787cdf0e10cSrcweir 												sal_Int32 nX1, nY1;
1788cdf0e10cSrcweir 
1789cdf0e10cSrcweir 												Imp_PrepareCoorExport(nX1, nY1, pPrevPos1, rObjectPos, rObjectSize,
1790cdf0e10cSrcweir 													mrViewBox, bScale, bTranslate);
1791cdf0e10cSrcweir 
1792cdf0e10cSrcweir 												// write a quadratic curveto entry (Q)
1793cdf0e10cSrcweir 												if(bRelative)
1794cdf0e10cSrcweir 												{
1795cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('q'))
1796cdf0e10cSrcweir 														aNewString += OUString(sal_Unicode('q'));
1797cdf0e10cSrcweir 
1798cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1799cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1800cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1801cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1802cdf0e10cSrcweir 
1803cdf0e10cSrcweir 													aLastCommand = sal_Unicode('q');
1804cdf0e10cSrcweir 												}
1805cdf0e10cSrcweir 												else
1806cdf0e10cSrcweir 												{
1807cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('Q'))
1808cdf0e10cSrcweir 														aNewString += OUString(sal_Unicode('Q'));
1809cdf0e10cSrcweir 
1810cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX1);
1811cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY1);
1812cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX);
1813cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY);
1814cdf0e10cSrcweir 
1815cdf0e10cSrcweir 													aLastCommand = sal_Unicode('Q');
1816cdf0e10cSrcweir 												}
1817cdf0e10cSrcweir 											}
1818cdf0e10cSrcweir 										}
1819cdf0e10cSrcweir 										else
1820cdf0e10cSrcweir 										{
1821cdf0e10cSrcweir #endif // TEST_QUADRATIC_CURVES
1822cdf0e10cSrcweir 											awt::Point aNewPoint(nPX_L, nPY_L);
1823cdf0e10cSrcweir 											bool bPrevPointIsSmooth(false);
1824cdf0e10cSrcweir 
1825cdf0e10cSrcweir 											if(drawing::PolygonFlags_SMOOTH == aPrevFlag3)
1826cdf0e10cSrcweir 											{
1827cdf0e10cSrcweir 												// get previous4 to see if it's a control point
1828cdf0e10cSrcweir 												awt::Point* pPrevPos4;
1829cdf0e10cSrcweir 												drawing::PolygonFlags aPrevFlag4;
1830cdf0e10cSrcweir 
1831cdf0e10cSrcweir 												Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1832cdf0e10cSrcweir 													pFlags->getArray(), a, nCnt, 4);
1833cdf0e10cSrcweir 
1834cdf0e10cSrcweir 												if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1835cdf0e10cSrcweir 												{
1836cdf0e10cSrcweir 													// okay, prevPos3 is smooth (c1) and prevPos4
1837cdf0e10cSrcweir 													// is existing control point. Test if it's even symmetric
1838cdf0e10cSrcweir 													// and thus the 'T' statement may be used.
1839cdf0e10cSrcweir 													::basegfx::B2DVector aVec1(pPrevPos4->X - pPrevPos3->X, pPrevPos4->Y - pPrevPos3->Y);
1840cdf0e10cSrcweir 													::basegfx::B2DVector aVec2(aNewPoint.X - pPrevPos3->X, aNewPoint.Y - pPrevPos3->Y);
1841cdf0e10cSrcweir 													bool bSameLength(false);
1842cdf0e10cSrcweir 													bool bSameDirection(false);
1843cdf0e10cSrcweir 
1844cdf0e10cSrcweir 													// get vector values
1845cdf0e10cSrcweir 													Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
1846cdf0e10cSrcweir 
1847cdf0e10cSrcweir 													if(bSameLength && bSameDirection)
1848cdf0e10cSrcweir 														bPrevPointIsSmooth = true;
1849cdf0e10cSrcweir 												}
1850cdf0e10cSrcweir 											}
1851cdf0e10cSrcweir 
1852cdf0e10cSrcweir 											if(bPrevPointIsSmooth)
1853cdf0e10cSrcweir 											{
1854cdf0e10cSrcweir 												// write a shorthand/smooth quadratic curveto entry (T)
1855cdf0e10cSrcweir 												if(bRelative)
1856cdf0e10cSrcweir 												{
1857cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('t'))
1858cdf0e10cSrcweir 														aNewString += String(sal_Unicode('t'));
1859cdf0e10cSrcweir 
1860cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1861cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1862cdf0e10cSrcweir 
1863cdf0e10cSrcweir 													aLastCommand = sal_Unicode('t');
1864cdf0e10cSrcweir 												}
1865cdf0e10cSrcweir 												else
1866cdf0e10cSrcweir 												{
1867cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('T'))
1868cdf0e10cSrcweir 														aNewString += String(sal_Unicode('T'));
1869cdf0e10cSrcweir 
1870cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX);
1871cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY);
1872cdf0e10cSrcweir 
1873cdf0e10cSrcweir 													aLastCommand = sal_Unicode('T');
1874cdf0e10cSrcweir 												}
1875cdf0e10cSrcweir 											}
1876cdf0e10cSrcweir 											else
1877cdf0e10cSrcweir 											{
1878cdf0e10cSrcweir 												// prepare coordinates
1879cdf0e10cSrcweir 												sal_Int32 nX1, nY1;
1880cdf0e10cSrcweir 
1881cdf0e10cSrcweir 												Imp_PrepareCoorExport(nX1, nY1, &aNewPoint, rObjectPos, rObjectSize,
1882cdf0e10cSrcweir 													mrViewBox, bScale, bTranslate);
1883cdf0e10cSrcweir 
1884cdf0e10cSrcweir 												// write a quadratic curveto entry (Q)
1885cdf0e10cSrcweir 												if(bRelative)
1886cdf0e10cSrcweir 												{
1887cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('q'))
1888cdf0e10cSrcweir 														aNewString += String(sal_Unicode('q'));
1889cdf0e10cSrcweir 
1890cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1891cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1892cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1893cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1894cdf0e10cSrcweir 
1895cdf0e10cSrcweir 													aLastCommand = sal_Unicode('q');
1896cdf0e10cSrcweir 												}
1897cdf0e10cSrcweir 												else
1898cdf0e10cSrcweir 												{
1899cdf0e10cSrcweir 													if(aLastCommand != sal_Unicode('Q'))
1900cdf0e10cSrcweir 														aNewString += String(sal_Unicode('Q'));
1901cdf0e10cSrcweir 
1902cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX1);
1903cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY1);
1904cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nX);
1905cdf0e10cSrcweir 													Imp_PutNumberCharWithSpace(aNewString, nY);
1906cdf0e10cSrcweir 
1907cdf0e10cSrcweir 													aLastCommand = sal_Unicode('Q');
1908cdf0e10cSrcweir 												}
1909cdf0e10cSrcweir 											}
1910cdf0e10cSrcweir #ifdef TEST_QUADRATIC_CURVES
1911cdf0e10cSrcweir 										}
1912cdf0e10cSrcweir #endif // TEST_QUADRATIC_CURVES
1913cdf0e10cSrcweir 									}
1914cdf0e10cSrcweir 									else
1915cdf0e10cSrcweir 									{
1916cdf0e10cSrcweir 										bool bPrevPointIsSymmetric(false);
1917cdf0e10cSrcweir 
1918cdf0e10cSrcweir 										if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
1919cdf0e10cSrcweir 										{
1920cdf0e10cSrcweir 											// get previous4 to see if it's a control point
1921cdf0e10cSrcweir 											awt::Point* pPrevPos4;
1922cdf0e10cSrcweir 											drawing::PolygonFlags aPrevFlag4;
1923cdf0e10cSrcweir 
1924cdf0e10cSrcweir 											Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1925cdf0e10cSrcweir 												pFlags->getArray(), a, nCnt, 4);
1926cdf0e10cSrcweir 
1927cdf0e10cSrcweir 											if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1928cdf0e10cSrcweir 											{
1929cdf0e10cSrcweir 												// okay, prevPos3 is symmetric (c2) and prevPos4
1930cdf0e10cSrcweir 												// is existing control point, the 's' statement can be used
1931cdf0e10cSrcweir 												bPrevPointIsSymmetric = true;
1932cdf0e10cSrcweir 											}
1933cdf0e10cSrcweir 										}
1934cdf0e10cSrcweir 
1935cdf0e10cSrcweir 										// prepare coordinates
1936cdf0e10cSrcweir 										sal_Int32 nX2, nY2;
1937cdf0e10cSrcweir 
1938cdf0e10cSrcweir 										Imp_PrepareCoorExport(nX2, nY2, pPrevPos1, rObjectPos, rObjectSize,
1939cdf0e10cSrcweir 											mrViewBox, bScale, bTranslate);
1940cdf0e10cSrcweir 
1941cdf0e10cSrcweir 										if(bPrevPointIsSymmetric)
1942cdf0e10cSrcweir 										{
1943cdf0e10cSrcweir 											// write a shorthand/smooth curveto entry (S)
1944cdf0e10cSrcweir 											if(bRelative)
1945cdf0e10cSrcweir 											{
1946cdf0e10cSrcweir 												if(aLastCommand != sal_Unicode('s'))
1947cdf0e10cSrcweir 													aNewString += String(sal_Unicode('s'));
1948cdf0e10cSrcweir 
1949cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
1950cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
1951cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1952cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1953cdf0e10cSrcweir 
1954cdf0e10cSrcweir 												aLastCommand = sal_Unicode('s');
1955cdf0e10cSrcweir 											}
1956cdf0e10cSrcweir 											else
1957cdf0e10cSrcweir 											{
1958cdf0e10cSrcweir 												if(aLastCommand != sal_Unicode('S'))
1959cdf0e10cSrcweir 													aNewString += String(sal_Unicode('S'));
1960cdf0e10cSrcweir 
1961cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX2);
1962cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY2);
1963cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX);
1964cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY);
1965cdf0e10cSrcweir 
1966cdf0e10cSrcweir 												aLastCommand = sal_Unicode('S');
1967cdf0e10cSrcweir 											}
1968cdf0e10cSrcweir 										}
1969cdf0e10cSrcweir 										else
1970cdf0e10cSrcweir 										{
1971cdf0e10cSrcweir 											// prepare coordinates
1972cdf0e10cSrcweir 											sal_Int32 nX1, nY1;
1973cdf0e10cSrcweir 
1974cdf0e10cSrcweir 											Imp_PrepareCoorExport(nX1, nY1, pPrevPos2, rObjectPos, rObjectSize,
1975cdf0e10cSrcweir 												mrViewBox, bScale, bTranslate);
1976cdf0e10cSrcweir 
1977cdf0e10cSrcweir 											// write a curveto entry (C)
1978cdf0e10cSrcweir 											if(bRelative)
1979cdf0e10cSrcweir 											{
1980cdf0e10cSrcweir 												if(aLastCommand != sal_Unicode('c'))
1981cdf0e10cSrcweir 													aNewString += String(sal_Unicode('c'));
1982cdf0e10cSrcweir 
1983cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1984cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1985cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
1986cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
1987cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1988cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1989cdf0e10cSrcweir 
1990cdf0e10cSrcweir 												aLastCommand = sal_Unicode('c');
1991cdf0e10cSrcweir 											}
1992cdf0e10cSrcweir 											else
1993cdf0e10cSrcweir 											{
1994cdf0e10cSrcweir 												if(aLastCommand != sal_Unicode('C'))
1995cdf0e10cSrcweir 													aNewString += String(sal_Unicode('C'));
1996cdf0e10cSrcweir 
1997cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX1);
1998cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY1);
1999cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX2);
2000cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY2);
2001cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nX);
2002cdf0e10cSrcweir 												Imp_PutNumberCharWithSpace(aNewString, nY);
2003cdf0e10cSrcweir 
2004cdf0e10cSrcweir 												aLastCommand = sal_Unicode('C');
2005cdf0e10cSrcweir 											}
2006cdf0e10cSrcweir 										}
2007cdf0e10cSrcweir 									}
2008cdf0e10cSrcweir 
2009cdf0e10cSrcweir 									// remember that current point IS written
2010cdf0e10cSrcweir 									bDidWriteAsCurve = true;
2011cdf0e10cSrcweir 
2012cdf0e10cSrcweir 									// remember new last position
2013cdf0e10cSrcweir 									mnLastX = nX;
2014cdf0e10cSrcweir 									mnLastY = nY;
2015cdf0e10cSrcweir 								}
2016cdf0e10cSrcweir 							}
2017cdf0e10cSrcweir 						}
2018cdf0e10cSrcweir 					}
2019cdf0e10cSrcweir 				}
2020cdf0e10cSrcweir 
2021cdf0e10cSrcweir 				if(!bDidWriteAsCurve)
2022cdf0e10cSrcweir 				{
2023cdf0e10cSrcweir 					// current point not yet written, prepare coordinates
2024cdf0e10cSrcweir 					sal_Int32 nX, nY;
2025cdf0e10cSrcweir 
2026cdf0e10cSrcweir 					Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
2027cdf0e10cSrcweir 						mrViewBox, bScale, bTranslate);
2028cdf0e10cSrcweir 
2029cdf0e10cSrcweir 					if(bDidWriteStart)
2030cdf0e10cSrcweir 					{
2031cdf0e10cSrcweir 						// write as normal point
2032cdf0e10cSrcweir 						if(mnLastX == nX)
2033cdf0e10cSrcweir 						{
2034cdf0e10cSrcweir 							if(bRelative)
2035cdf0e10cSrcweir 							{
2036cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('v'))
2037cdf0e10cSrcweir 									aNewString += String(sal_Unicode('v'));
2038cdf0e10cSrcweir 
2039cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2040cdf0e10cSrcweir 
2041cdf0e10cSrcweir 								aLastCommand = sal_Unicode('v');
2042cdf0e10cSrcweir 							}
2043cdf0e10cSrcweir 							else
2044cdf0e10cSrcweir 							{
2045cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('V'))
2046cdf0e10cSrcweir 									aNewString += String(sal_Unicode('V'));
2047cdf0e10cSrcweir 
2048cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nY);
2049cdf0e10cSrcweir 
2050cdf0e10cSrcweir 								aLastCommand = sal_Unicode('V');
2051cdf0e10cSrcweir 							}
2052cdf0e10cSrcweir 						}
2053cdf0e10cSrcweir 						else if(mnLastY == nY)
2054cdf0e10cSrcweir 						{
2055cdf0e10cSrcweir 							if(bRelative)
2056cdf0e10cSrcweir 							{
2057cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('h'))
2058cdf0e10cSrcweir 									aNewString += String(sal_Unicode('h'));
2059cdf0e10cSrcweir 
2060cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2061cdf0e10cSrcweir 
2062cdf0e10cSrcweir 								aLastCommand = sal_Unicode('h');
2063cdf0e10cSrcweir 							}
2064cdf0e10cSrcweir 							else
2065cdf0e10cSrcweir 							{
2066cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('H'))
2067cdf0e10cSrcweir 									aNewString += String(sal_Unicode('H'));
2068cdf0e10cSrcweir 
2069cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nX);
2070cdf0e10cSrcweir 
2071cdf0e10cSrcweir 								aLastCommand = sal_Unicode('H');
2072cdf0e10cSrcweir 							}
2073cdf0e10cSrcweir 						}
2074cdf0e10cSrcweir 						else
2075cdf0e10cSrcweir 						{
2076cdf0e10cSrcweir 							if(bRelative)
2077cdf0e10cSrcweir 							{
2078cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('l'))
2079cdf0e10cSrcweir 									aNewString += String(sal_Unicode('l'));
2080cdf0e10cSrcweir 
2081cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2082cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2083cdf0e10cSrcweir 
2084cdf0e10cSrcweir 								aLastCommand = sal_Unicode('l');
2085cdf0e10cSrcweir 							}
2086cdf0e10cSrcweir 							else
2087cdf0e10cSrcweir 							{
2088cdf0e10cSrcweir 								if(aLastCommand != sal_Unicode('L'))
2089cdf0e10cSrcweir 									aNewString += String(sal_Unicode('L'));
2090cdf0e10cSrcweir 
2091cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nX);
2092cdf0e10cSrcweir 								Imp_PutNumberCharWithSpace(aNewString, nY);
2093cdf0e10cSrcweir 
2094cdf0e10cSrcweir 								aLastCommand = sal_Unicode('L');
2095cdf0e10cSrcweir 							}
2096cdf0e10cSrcweir 						}
2097cdf0e10cSrcweir 					}
2098cdf0e10cSrcweir 					else
2099cdf0e10cSrcweir 					{
2100cdf0e10cSrcweir 						// write as start point
2101cdf0e10cSrcweir 						if(bRelative)
2102cdf0e10cSrcweir 						{
2103cdf0e10cSrcweir 							aNewString += String(sal_Unicode('m'));
2104cdf0e10cSrcweir 
2105cdf0e10cSrcweir 							Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2106cdf0e10cSrcweir 							Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2107cdf0e10cSrcweir 
2108cdf0e10cSrcweir 							aLastCommand = sal_Unicode('l');
2109cdf0e10cSrcweir 						}
2110cdf0e10cSrcweir 						else
2111cdf0e10cSrcweir 						{
2112cdf0e10cSrcweir 							aNewString += String(sal_Unicode('M'));
2113cdf0e10cSrcweir 
2114cdf0e10cSrcweir 							Imp_PutNumberCharWithSpace(aNewString, nX);
2115cdf0e10cSrcweir 							Imp_PutNumberCharWithSpace(aNewString, nY);
2116cdf0e10cSrcweir 
2117cdf0e10cSrcweir 							aLastCommand = sal_Unicode('L');
2118cdf0e10cSrcweir 						}
2119cdf0e10cSrcweir 
2120cdf0e10cSrcweir 						// remember start written
2121cdf0e10cSrcweir 						bDidWriteStart = true;
2122cdf0e10cSrcweir 					}
2123cdf0e10cSrcweir 
2124cdf0e10cSrcweir 					// remember new last position
2125cdf0e10cSrcweir 					mnLastX = nX;
2126cdf0e10cSrcweir 					mnLastY = nY;
2127cdf0e10cSrcweir 				}
2128cdf0e10cSrcweir 			}
2129cdf0e10cSrcweir 
2130cdf0e10cSrcweir 			// next point
2131cdf0e10cSrcweir 			pPointArray++;
2132cdf0e10cSrcweir 			pFlagArray++;
2133cdf0e10cSrcweir 		}
2134cdf0e10cSrcweir 
2135cdf0e10cSrcweir 		// close path if closed poly
2136cdf0e10cSrcweir 		if(bClosed)
2137cdf0e10cSrcweir 		{
2138cdf0e10cSrcweir 			if(bRelative)
2139cdf0e10cSrcweir 				aNewString += String(sal_Unicode('z'));
2140cdf0e10cSrcweir 			else
2141cdf0e10cSrcweir 				aNewString += String(sal_Unicode('Z'));
2142cdf0e10cSrcweir 		}
2143cdf0e10cSrcweir 
2144cdf0e10cSrcweir 		// append new string
2145cdf0e10cSrcweir 		msString += aNewString;
2146cdf0e10cSrcweir 	}
2147cdf0e10cSrcweir }
2148cdf0e10cSrcweir 
2149cdf0e10cSrcweir // #100617# Linear double reader
2150cdf0e10cSrcweir double Imp_ImportDoubleAndSpaces(
2151cdf0e10cSrcweir 	double fRetval, const OUString& rStr, sal_Int32& rPos,
2152cdf0e10cSrcweir 	const sal_Int32 nLen, const SvXMLUnitConverter& rConv)
2153cdf0e10cSrcweir {
2154cdf0e10cSrcweir 	fRetval = Imp_GetDoubleChar(rStr, rPos, nLen, rConv, fRetval);
2155cdf0e10cSrcweir 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
2156cdf0e10cSrcweir 	return fRetval;
2157cdf0e10cSrcweir }
2158cdf0e10cSrcweir 
2159cdf0e10cSrcweir // #100617# Allow to read doubles, too. This will need to be changed to
2160cdf0e10cSrcweir // the usage of Imp_ImportDoubleAndSpaces(...). For now, this is sufficient
2161cdf0e10cSrcweir // since the interface cannot transport doubles.
2162cdf0e10cSrcweir sal_Int32 Imp_ImportNumberAndSpaces(
2163cdf0e10cSrcweir 	sal_Int32 nRetval, const OUString& rStr, sal_Int32& rPos,
2164cdf0e10cSrcweir 	const sal_Int32 nLen, const SvXMLUnitConverter& rConv)
2165cdf0e10cSrcweir {
2166cdf0e10cSrcweir 	nRetval = FRound(Imp_ImportDoubleAndSpaces(double(nRetval), rStr, rPos, nLen, rConv));
2167cdf0e10cSrcweir 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
2168cdf0e10cSrcweir 	return nRetval;
2169cdf0e10cSrcweir }
2170cdf0e10cSrcweir 
2171cdf0e10cSrcweir void Imp_PrepareCoorImport(sal_Int32& nX, sal_Int32& nY,
2172cdf0e10cSrcweir 	const awt::Point& rObjectPos, const awt::Size& rObjectSize,
2173cdf0e10cSrcweir 	const SdXMLImExViewBox& rViewBox, const bool bScale, const bool bTranslate)
2174cdf0e10cSrcweir {
2175cdf0e10cSrcweir 	if(bTranslate)
2176cdf0e10cSrcweir 	{
2177cdf0e10cSrcweir 		nX -= rViewBox.GetX();
2178cdf0e10cSrcweir 		nY -= rViewBox.GetY();
2179cdf0e10cSrcweir 	}
2180cdf0e10cSrcweir 
2181cdf0e10cSrcweir 	if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight())
2182cdf0e10cSrcweir 	{
2183cdf0e10cSrcweir 		nX = (nX * rObjectSize.Width) / rViewBox.GetWidth();
2184cdf0e10cSrcweir 		nY = (nY * rObjectSize.Height) / rViewBox.GetHeight();
2185cdf0e10cSrcweir 	}
2186cdf0e10cSrcweir 
2187cdf0e10cSrcweir 	nX += rObjectPos.X;
2188cdf0e10cSrcweir 	nY += rObjectPos.Y;
2189cdf0e10cSrcweir }
2190cdf0e10cSrcweir 
2191cdf0e10cSrcweir void Imp_AddExportPoints(sal_Int32 nX, sal_Int32 nY,
2192cdf0e10cSrcweir 	awt::Point* pPoints, drawing::PolygonFlags* pFlags,
2193cdf0e10cSrcweir 	const sal_Int32 nInnerIndex,
2194cdf0e10cSrcweir 	drawing::PolygonFlags eFlag)
2195cdf0e10cSrcweir {
2196cdf0e10cSrcweir 	if(pPoints)
2197cdf0e10cSrcweir 		pPoints[nInnerIndex] = awt::Point( nX, nY );
2198cdf0e10cSrcweir 
2199cdf0e10cSrcweir 	if(pFlags)
2200cdf0e10cSrcweir 		pFlags[nInnerIndex] = eFlag;
2201cdf0e10cSrcweir }
2202cdf0e10cSrcweir 
2203cdf0e10cSrcweir void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection)
2204cdf0e10cSrcweir {
2205cdf0e10cSrcweir 	const sal_Int32 nLen1(FRound(aVec1.getLength()));
2206cdf0e10cSrcweir 	const sal_Int32 nLen2(FRound(aVec2.getLength()));
2207cdf0e10cSrcweir 	aVec1.normalize();
2208cdf0e10cSrcweir 	aVec2.normalize();
2209cdf0e10cSrcweir 	aVec1 += aVec2;
2210cdf0e10cSrcweir 	const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0)));
2211cdf0e10cSrcweir 
2212cdf0e10cSrcweir 	bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL);
2213cdf0e10cSrcweir 	bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL);
2214cdf0e10cSrcweir }
2215cdf0e10cSrcweir 
2216cdf0e10cSrcweir void Imp_CorrectPolygonFlag(const sal_uInt32 nInnerIndex, const awt::Point* const pInnerSequence,
2217cdf0e10cSrcweir 	drawing::PolygonFlags* const pInnerFlags, const sal_Int32 nX1, const sal_Int32 nY1)
2218cdf0e10cSrcweir {
2219cdf0e10cSrcweir 	if(nInnerIndex)
2220cdf0e10cSrcweir 	{
2221cdf0e10cSrcweir 		const awt::Point aPPrev1 = pInnerSequence[nInnerIndex - 1];
2222cdf0e10cSrcweir 
2223cdf0e10cSrcweir 		if(nInnerIndex > 1)
2224cdf0e10cSrcweir 		{
2225cdf0e10cSrcweir 			const awt::Point aPPrev2 = pInnerSequence[nInnerIndex - 2];
2226cdf0e10cSrcweir 			const drawing::PolygonFlags aFPrev2 = pInnerFlags[nInnerIndex - 2];
2227cdf0e10cSrcweir 			::basegfx::B2DVector aVec1(aPPrev2.X - aPPrev1.X, aPPrev2.Y - aPPrev1.Y);
2228cdf0e10cSrcweir 			::basegfx::B2DVector aVec2(nX1 - aPPrev1.X, nY1 - aPPrev1.Y);
2229cdf0e10cSrcweir 			bool bSameLength(false);
2230cdf0e10cSrcweir 			bool bSameDirection(false);
2231cdf0e10cSrcweir 
2232cdf0e10cSrcweir 			// get vector values
2233cdf0e10cSrcweir 			Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
2234cdf0e10cSrcweir 
2235cdf0e10cSrcweir 			if(drawing::PolygonFlags_CONTROL == aFPrev2)
2236cdf0e10cSrcweir 			{
2237cdf0e10cSrcweir 				// point before is a control point
2238cdf0e10cSrcweir 				if(bSameDirection)
2239cdf0e10cSrcweir 				{
2240cdf0e10cSrcweir 					if(bSameLength)
2241cdf0e10cSrcweir 					{
2242cdf0e10cSrcweir 						// set to PolygonFlags_SYMMETRIC
2243cdf0e10cSrcweir 						pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC;
2244cdf0e10cSrcweir 					}
2245cdf0e10cSrcweir 					else
2246cdf0e10cSrcweir 					{
2247cdf0e10cSrcweir 						// set to PolygonFlags_SMOOTH
2248cdf0e10cSrcweir 						pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
2249cdf0e10cSrcweir 					}
2250cdf0e10cSrcweir 				}
2251cdf0e10cSrcweir 				else
2252cdf0e10cSrcweir 				{
2253cdf0e10cSrcweir 					// set to PolygonFlags_NORMAL
2254cdf0e10cSrcweir 					pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
2255cdf0e10cSrcweir 				}
2256cdf0e10cSrcweir 			}
2257cdf0e10cSrcweir 			else
2258cdf0e10cSrcweir 			{
2259cdf0e10cSrcweir 				// point before is a simple curve point
2260cdf0e10cSrcweir 				if(bSameDirection)
2261cdf0e10cSrcweir 				{
2262cdf0e10cSrcweir 					// set to PolygonFlags_SMOOTH
2263cdf0e10cSrcweir 					pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
2264cdf0e10cSrcweir 				}
2265cdf0e10cSrcweir 				else
2266cdf0e10cSrcweir 				{
2267cdf0e10cSrcweir 					// set to PolygonFlags_NORMAL
2268cdf0e10cSrcweir 					pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
2269cdf0e10cSrcweir 				}
2270cdf0e10cSrcweir 			}
2271cdf0e10cSrcweir 		}
2272cdf0e10cSrcweir 		else
2273cdf0e10cSrcweir 		{
2274cdf0e10cSrcweir 			// no point before starpoint, set type to PolygonFlags_NORMAL
2275cdf0e10cSrcweir 			pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL;
2276cdf0e10cSrcweir 		}
2277cdf0e10cSrcweir 	}
2278cdf0e10cSrcweir }
2279cdf0e10cSrcweir 
2280cdf0e10cSrcweir SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew,
2281cdf0e10cSrcweir 	const SdXMLImExViewBox& rViewBox,
2282cdf0e10cSrcweir 	const awt::Point& rObjectPos,
2283cdf0e10cSrcweir 	const awt::Size& rObjectSize,
2284cdf0e10cSrcweir 	const SvXMLUnitConverter& rConv)
2285cdf0e10cSrcweir :	msString( rNew ),
2286cdf0e10cSrcweir 	mrViewBox( rViewBox ),
2287cdf0e10cSrcweir 	mbIsClosed( false ),
2288cdf0e10cSrcweir 	mbIsCurve( false ),
2289cdf0e10cSrcweir 	mnLastX( 0L ),
2290cdf0e10cSrcweir 	mnLastY( 0L ),
2291cdf0e10cSrcweir 	maPoly( 0L ),
2292cdf0e10cSrcweir 	maFlag( 0L )
2293cdf0e10cSrcweir {
2294cdf0e10cSrcweir 	// convert string to polygon
2295cdf0e10cSrcweir 	const OUString aStr(msString.getStr(), msString.getLength());
2296cdf0e10cSrcweir 	const sal_Int32 nLen(aStr.getLength());
2297cdf0e10cSrcweir 	sal_Int32 nPos(0);
2298cdf0e10cSrcweir 	sal_Int32 nNumPolys(0L);
2299cdf0e10cSrcweir 	bool bEllipticalArc(false);
2300cdf0e10cSrcweir 
2301cdf0e10cSrcweir 	// object size and ViewBox size different?
2302cdf0e10cSrcweir 	bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
2303cdf0e10cSrcweir 		|| rObjectSize.Height != mrViewBox.GetHeight());
2304cdf0e10cSrcweir 	bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
2305cdf0e10cSrcweir 
2306cdf0e10cSrcweir 	// first loop: count polys and get flags
2307cdf0e10cSrcweir 	Imp_SkipSpaces(aStr, nPos, nLen);
2308cdf0e10cSrcweir 
2309cdf0e10cSrcweir 	while(nPos < nLen)
2310cdf0e10cSrcweir 	{
2311cdf0e10cSrcweir 		switch(aStr[nPos++])
2312cdf0e10cSrcweir 		{
2313cdf0e10cSrcweir 			case 'Z' :
2314cdf0e10cSrcweir 			case 'z' :
2315cdf0e10cSrcweir 			{
2316cdf0e10cSrcweir 				break;
2317cdf0e10cSrcweir 			}
2318cdf0e10cSrcweir 			case 'M' :
2319cdf0e10cSrcweir 			case 'm' :
2320cdf0e10cSrcweir 			{
2321cdf0e10cSrcweir 				nNumPolys++;
2322cdf0e10cSrcweir 				break;
2323cdf0e10cSrcweir 			}
2324cdf0e10cSrcweir 			case 'S' :
2325cdf0e10cSrcweir 			case 's' :
2326cdf0e10cSrcweir 			case 'C' :
2327cdf0e10cSrcweir 			case 'c' :
2328cdf0e10cSrcweir 			case 'Q' :
2329cdf0e10cSrcweir 			case 'q' :
2330cdf0e10cSrcweir 			case 'T' :
2331cdf0e10cSrcweir 			case 't' :
2332cdf0e10cSrcweir 			{
2333cdf0e10cSrcweir 				mbIsCurve = true;
2334cdf0e10cSrcweir 				break;
2335cdf0e10cSrcweir 			}
2336cdf0e10cSrcweir 			case 'L' :
2337cdf0e10cSrcweir 			case 'l' :
2338cdf0e10cSrcweir 			case 'H' :
2339cdf0e10cSrcweir 			case 'h' :
2340cdf0e10cSrcweir 			case 'V' :
2341cdf0e10cSrcweir 			case 'v' :
2342cdf0e10cSrcweir 			{
2343cdf0e10cSrcweir 				// normal, interpreted values. All okay.
2344cdf0e10cSrcweir 				break;
2345cdf0e10cSrcweir 			}
2346cdf0e10cSrcweir 			case 'A' :
2347cdf0e10cSrcweir 			case 'a' :
2348cdf0e10cSrcweir 			{
2349cdf0e10cSrcweir 				// Not yet interpreted value.
2350cdf0e10cSrcweir 				bEllipticalArc = true;
2351cdf0e10cSrcweir 				break;
2352cdf0e10cSrcweir 			}
2353cdf0e10cSrcweir 		}
2354cdf0e10cSrcweir 	}
2355cdf0e10cSrcweir 
2356cdf0e10cSrcweir 	DBG_ASSERT(!bEllipticalArc, "XMLIMP: non-interpreted tags in svg:d element!");
2357cdf0e10cSrcweir 
2358cdf0e10cSrcweir 	if(nNumPolys)
2359cdf0e10cSrcweir 	{
2360cdf0e10cSrcweir 		// alloc arrays
2361cdf0e10cSrcweir 		maPoly.realloc(nNumPolys);
2362cdf0e10cSrcweir 		if(IsCurve())
2363cdf0e10cSrcweir 			maFlag.realloc(nNumPolys);
2364cdf0e10cSrcweir 
2365cdf0e10cSrcweir 		// get outer sequences
2366cdf0e10cSrcweir 		drawing::PointSequence* pOuterSequence = maPoly.getArray();
2367cdf0e10cSrcweir 		drawing::FlagSequence* pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L;
2368cdf0e10cSrcweir 
2369cdf0e10cSrcweir 		// prepare new loop, count
2370cdf0e10cSrcweir 		sal_uInt32 nPointCount(0L);
2371cdf0e10cSrcweir 		nPos = 0;
2372cdf0e10cSrcweir 		Imp_SkipSpaces(aStr, nPos, nLen);
2373cdf0e10cSrcweir 
2374cdf0e10cSrcweir 		// #104076# reset closed flag for next to be started polygon
2375cdf0e10cSrcweir 		mbIsClosed = false;
2376cdf0e10cSrcweir 
2377cdf0e10cSrcweir 		while(nPos < nLen)
2378cdf0e10cSrcweir 		{
2379cdf0e10cSrcweir 			switch(aStr[nPos])
2380cdf0e10cSrcweir 			{
2381cdf0e10cSrcweir 				case 'z' :
2382cdf0e10cSrcweir 				case 'Z' :
2383cdf0e10cSrcweir 				{
2384cdf0e10cSrcweir 					nPos++;
2385cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2386cdf0e10cSrcweir 
2387cdf0e10cSrcweir 					// #104076# remember closed state of current polygon
2388cdf0e10cSrcweir 					mbIsClosed = true;
2389cdf0e10cSrcweir 
2390cdf0e10cSrcweir 					break;
2391cdf0e10cSrcweir 				}
2392cdf0e10cSrcweir 				case 'm' :
2393cdf0e10cSrcweir 				case 'M' :
2394cdf0e10cSrcweir 				{
2395cdf0e10cSrcweir 					// new poly starts, end-process current poly
2396cdf0e10cSrcweir 					if(nPointCount)
2397cdf0e10cSrcweir 					{
2398cdf0e10cSrcweir 						// #104076# If this partial polygon is closed, use one more point
2399cdf0e10cSrcweir 						// to represent that
2400cdf0e10cSrcweir 						if(mbIsClosed)
2401cdf0e10cSrcweir 						{
2402cdf0e10cSrcweir 							nPointCount++;
2403cdf0e10cSrcweir 						}
2404cdf0e10cSrcweir 
2405cdf0e10cSrcweir 						pOuterSequence->realloc(nPointCount);
2406cdf0e10cSrcweir 						pOuterSequence++;
2407cdf0e10cSrcweir 
2408cdf0e10cSrcweir 						if(pOuterFlags)
2409cdf0e10cSrcweir 						{
2410cdf0e10cSrcweir 							pOuterFlags->realloc(nPointCount);
2411cdf0e10cSrcweir 							pOuterFlags++;
2412cdf0e10cSrcweir 						}
2413cdf0e10cSrcweir 
2414cdf0e10cSrcweir 						// reset point count for next polygon
2415cdf0e10cSrcweir 						nPointCount = 0L;
2416cdf0e10cSrcweir 					}
2417cdf0e10cSrcweir 
2418cdf0e10cSrcweir 					// #104076# reset closed flag for next to be started polygon
2419cdf0e10cSrcweir 					mbIsClosed = false;
2420cdf0e10cSrcweir 
2421cdf0e10cSrcweir 					// NO break, continue in next case
2422cdf0e10cSrcweir 				}
2423cdf0e10cSrcweir 				case 'L' :
2424cdf0e10cSrcweir 				case 'l' :
2425cdf0e10cSrcweir 				{
2426cdf0e10cSrcweir 					nPos++;
2427cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2428cdf0e10cSrcweir 
2429cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2430cdf0e10cSrcweir 					{
2431cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2432cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2433cdf0e10cSrcweir 						nPointCount++;
2434cdf0e10cSrcweir 					}
2435cdf0e10cSrcweir 					break;
2436cdf0e10cSrcweir 				}
2437cdf0e10cSrcweir 				case 'H' :
2438cdf0e10cSrcweir 				case 'h' :
2439cdf0e10cSrcweir 				case 'V' :
2440cdf0e10cSrcweir 				case 'v' :
2441cdf0e10cSrcweir 				{
2442cdf0e10cSrcweir 					nPos++;
2443cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2444cdf0e10cSrcweir 
2445cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2446cdf0e10cSrcweir 					{
2447cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2448cdf0e10cSrcweir 						nPointCount++;
2449cdf0e10cSrcweir 					}
2450cdf0e10cSrcweir 					break;
2451cdf0e10cSrcweir 				}
2452cdf0e10cSrcweir 				case 'S' :
2453cdf0e10cSrcweir 				case 's' :
2454cdf0e10cSrcweir 				{
2455cdf0e10cSrcweir 					nPos++;
2456cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2457cdf0e10cSrcweir 
2458cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2459cdf0e10cSrcweir 					{
2460cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2461cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2462cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2463cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2464cdf0e10cSrcweir 						nPointCount += 3;
2465cdf0e10cSrcweir 					}
2466cdf0e10cSrcweir 					break;
2467cdf0e10cSrcweir 				}
2468cdf0e10cSrcweir 				case 'C' :
2469cdf0e10cSrcweir 				case 'c' :
2470cdf0e10cSrcweir 				{
2471cdf0e10cSrcweir 					nPos++;
2472cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2473cdf0e10cSrcweir 
2474cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2475cdf0e10cSrcweir 					{
2476cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2477cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2478cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2479cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2480cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2481cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2482cdf0e10cSrcweir 						nPointCount += 3;
2483cdf0e10cSrcweir 					}
2484cdf0e10cSrcweir 					break;
2485cdf0e10cSrcweir 				}
2486cdf0e10cSrcweir 
2487cdf0e10cSrcweir 				// #100617# quadratic beziers, supported as cubic ones
2488cdf0e10cSrcweir 				case 'Q' :
2489cdf0e10cSrcweir 				case 'q' :
2490cdf0e10cSrcweir 				{
2491cdf0e10cSrcweir 					nPos++;
2492cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2493cdf0e10cSrcweir 
2494cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2495cdf0e10cSrcweir 					{
2496cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2497cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2498cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2499cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2500cdf0e10cSrcweir 
2501cdf0e10cSrcweir 						// use three points since quadratic is imported as cubic
2502cdf0e10cSrcweir 						nPointCount += 3;
2503cdf0e10cSrcweir 					}
2504cdf0e10cSrcweir 					break;
2505cdf0e10cSrcweir 				}
2506cdf0e10cSrcweir 
2507cdf0e10cSrcweir 				// #100617# relative quadratic beziers, supported as cubic ones
2508cdf0e10cSrcweir 				case 'T' :
2509cdf0e10cSrcweir 				case 't' :
2510cdf0e10cSrcweir 				{
2511cdf0e10cSrcweir 					nPos++;
2512cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2513cdf0e10cSrcweir 
2514cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2515cdf0e10cSrcweir 					{
2516cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2517cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2518cdf0e10cSrcweir 
2519cdf0e10cSrcweir 						// use three points since quadratic is imported as cubic
2520cdf0e10cSrcweir 						nPointCount += 3;
2521cdf0e10cSrcweir 					}
2522cdf0e10cSrcweir 					break;
2523cdf0e10cSrcweir 				}
2524cdf0e10cSrcweir 
2525cdf0e10cSrcweir 				// #100617# not yet supported: elliptical arc
2526cdf0e10cSrcweir 				case 'A' :
2527cdf0e10cSrcweir 				case 'a' :
2528cdf0e10cSrcweir 				{
2529cdf0e10cSrcweir 					DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
2530cdf0e10cSrcweir 					nPos++;
2531cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2532cdf0e10cSrcweir 
2533cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2534cdf0e10cSrcweir 					{
2535cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2536cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2537cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2538cdf0e10cSrcweir 						Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
2539cdf0e10cSrcweir 						Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
2540cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2541cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2542cdf0e10cSrcweir 					}
2543cdf0e10cSrcweir 					break;
2544cdf0e10cSrcweir 				}
2545cdf0e10cSrcweir 
2546cdf0e10cSrcweir 				default:
2547cdf0e10cSrcweir 				{
2548cdf0e10cSrcweir 					nPos++;
2549cdf0e10cSrcweir 					DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
2550cdf0e10cSrcweir 					break;
2551cdf0e10cSrcweir 				}
2552cdf0e10cSrcweir 			}
2553cdf0e10cSrcweir 		}
2554cdf0e10cSrcweir 
2555cdf0e10cSrcweir 		// alloc last poly (when points used)
2556cdf0e10cSrcweir 		if(nPointCount)
2557cdf0e10cSrcweir 		{
2558cdf0e10cSrcweir 			// #104076# If this partial polygon is closed, use one more point
2559cdf0e10cSrcweir 			// to represent that
2560cdf0e10cSrcweir 			if(mbIsClosed)
2561cdf0e10cSrcweir 			{
2562cdf0e10cSrcweir 				nPointCount++;
2563cdf0e10cSrcweir 			}
2564cdf0e10cSrcweir 
2565cdf0e10cSrcweir 			pOuterSequence->realloc(nPointCount);
2566cdf0e10cSrcweir 			pOuterSequence++;
2567cdf0e10cSrcweir 
2568cdf0e10cSrcweir 			if(pOuterFlags)
2569cdf0e10cSrcweir 			{
2570cdf0e10cSrcweir 				pOuterFlags->realloc(nPointCount);
2571cdf0e10cSrcweir 				pOuterFlags++;
2572cdf0e10cSrcweir 			}
2573cdf0e10cSrcweir 		}
2574cdf0e10cSrcweir 
2575cdf0e10cSrcweir 		// set pointers back
2576cdf0e10cSrcweir 		pOuterSequence = maPoly.getArray();
2577cdf0e10cSrcweir 		pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L;
2578cdf0e10cSrcweir 		awt::Point* pNotSoInnerSequence = 0L;
2579cdf0e10cSrcweir 		drawing::PolygonFlags* pNotSoInnerFlags = 0L;
2580cdf0e10cSrcweir 		sal_uInt32 nInnerIndex(0L);
2581cdf0e10cSrcweir 
2582cdf0e10cSrcweir 		// prepare new loop, read points
2583cdf0e10cSrcweir 		nPos = 0;
2584cdf0e10cSrcweir 		Imp_SkipSpaces(aStr, nPos, nLen);
2585cdf0e10cSrcweir 
2586cdf0e10cSrcweir 		// #104076# reset closed flag for next to be started polygon
2587cdf0e10cSrcweir 		mbIsClosed = false;
2588cdf0e10cSrcweir 
2589cdf0e10cSrcweir 		while(nPos < nLen)
2590cdf0e10cSrcweir 		{
2591cdf0e10cSrcweir 			bool bRelative(false);
2592cdf0e10cSrcweir 
2593cdf0e10cSrcweir 			switch(aStr[nPos])
2594cdf0e10cSrcweir 			{
2595cdf0e10cSrcweir 				case 'z' :
2596cdf0e10cSrcweir 				case 'Z' :
2597cdf0e10cSrcweir 				{
2598cdf0e10cSrcweir 					nPos++;
2599cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2600cdf0e10cSrcweir 
2601cdf0e10cSrcweir 					// #104076# remember closed state of current polygon
2602cdf0e10cSrcweir 					mbIsClosed = true;
2603cdf0e10cSrcweir 
2604cdf0e10cSrcweir 					// closed: add first point again
2605cdf0e10cSrcweir 					// sal_Int32 nX(pInnerSequence[0].X);
2606cdf0e10cSrcweir 					// sal_Int32 nY(pInnerSequence[0].Y);
2607cdf0e10cSrcweir 					// Imp_AddExportPoints(nX, nY, pInnerSequence, pInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2608cdf0e10cSrcweir 
2609cdf0e10cSrcweir 					break;
2610cdf0e10cSrcweir 				}
2611cdf0e10cSrcweir 
2612cdf0e10cSrcweir 				case 'm' :
2613cdf0e10cSrcweir 				{
2614cdf0e10cSrcweir 					bRelative = true;
2615cdf0e10cSrcweir 				}
2616cdf0e10cSrcweir 				case 'M' :
2617cdf0e10cSrcweir 				{
2618cdf0e10cSrcweir 					// #104076# end-process current poly
2619cdf0e10cSrcweir 					if(mbIsClosed)
2620cdf0e10cSrcweir 					{
2621cdf0e10cSrcweir 						if(pNotSoInnerSequence)
2622cdf0e10cSrcweir 						{
2623cdf0e10cSrcweir 							// closed: add first point again
2624cdf0e10cSrcweir 							sal_Int32 nX(pNotSoInnerSequence[0].X);
2625cdf0e10cSrcweir 							sal_Int32 nY(pNotSoInnerSequence[0].Y);
2626cdf0e10cSrcweir 							Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2627cdf0e10cSrcweir 						}
2628cdf0e10cSrcweir 
2629cdf0e10cSrcweir 						// reset closed flag for next to be started polygon
2630cdf0e10cSrcweir 						mbIsClosed = false;
2631cdf0e10cSrcweir 					}
2632cdf0e10cSrcweir 
2633cdf0e10cSrcweir 					// next poly
2634cdf0e10cSrcweir 					pNotSoInnerSequence = pOuterSequence->getArray();
2635cdf0e10cSrcweir 					pOuterSequence++;
2636cdf0e10cSrcweir 
2637cdf0e10cSrcweir 					if(pOuterFlags)
2638cdf0e10cSrcweir 					{
2639cdf0e10cSrcweir 						pNotSoInnerFlags = pOuterFlags->getArray();
2640cdf0e10cSrcweir 						pOuterFlags++;
2641cdf0e10cSrcweir 					}
2642cdf0e10cSrcweir 
2643cdf0e10cSrcweir 					nInnerIndex = 0L;
2644cdf0e10cSrcweir 
2645cdf0e10cSrcweir 					nPos++;
2646cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2647cdf0e10cSrcweir 
2648cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2649cdf0e10cSrcweir 					{
2650cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2651cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2652cdf0e10cSrcweir 
2653cdf0e10cSrcweir 						if(bRelative)
2654cdf0e10cSrcweir 						{
2655cdf0e10cSrcweir 							nX += mnLastX;
2656cdf0e10cSrcweir 							nY += mnLastY;
2657cdf0e10cSrcweir 						}
2658cdf0e10cSrcweir 
2659cdf0e10cSrcweir 						// set last position
2660cdf0e10cSrcweir 						mnLastX = nX;
2661cdf0e10cSrcweir 						mnLastY = nY;
2662cdf0e10cSrcweir 
2663cdf0e10cSrcweir 						// calc transform and add point and flag
2664cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2665cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2666cdf0e10cSrcweir 					}
2667cdf0e10cSrcweir 					break;
2668cdf0e10cSrcweir 				}
2669cdf0e10cSrcweir 
2670cdf0e10cSrcweir 				case 'l' :
2671cdf0e10cSrcweir 				{
2672cdf0e10cSrcweir 					bRelative = true;
2673cdf0e10cSrcweir 				}
2674cdf0e10cSrcweir 				case 'L' :
2675cdf0e10cSrcweir 				{
2676cdf0e10cSrcweir 					nPos++;
2677cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2678cdf0e10cSrcweir 
2679cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2680cdf0e10cSrcweir 					{
2681cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2682cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2683cdf0e10cSrcweir 
2684cdf0e10cSrcweir 						if(bRelative)
2685cdf0e10cSrcweir 						{
2686cdf0e10cSrcweir 							nX += mnLastX;
2687cdf0e10cSrcweir 							nY += mnLastY;
2688cdf0e10cSrcweir 						}
2689cdf0e10cSrcweir 
2690cdf0e10cSrcweir 						// set last position
2691cdf0e10cSrcweir 						mnLastX = nX;
2692cdf0e10cSrcweir 						mnLastY = nY;
2693cdf0e10cSrcweir 
2694cdf0e10cSrcweir 						// calc transform and add point and flag
2695cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2696cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2697cdf0e10cSrcweir 					}
2698cdf0e10cSrcweir 					break;
2699cdf0e10cSrcweir 				}
2700cdf0e10cSrcweir 
2701cdf0e10cSrcweir 				case 'h' :
2702cdf0e10cSrcweir 				{
2703cdf0e10cSrcweir 					bRelative = true;
2704cdf0e10cSrcweir 				}
2705cdf0e10cSrcweir 				case 'H' :
2706cdf0e10cSrcweir 				{
2707cdf0e10cSrcweir 					nPos++;
2708cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2709cdf0e10cSrcweir 
2710cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2711cdf0e10cSrcweir 					{
2712cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2713cdf0e10cSrcweir 						sal_Int32 nY(mnLastY);
2714cdf0e10cSrcweir 
2715cdf0e10cSrcweir 						if(bRelative)
2716cdf0e10cSrcweir 							nX += mnLastX;
2717cdf0e10cSrcweir 
2718cdf0e10cSrcweir 						// set last position
2719cdf0e10cSrcweir 						mnLastX = nX;
2720cdf0e10cSrcweir 
2721cdf0e10cSrcweir 						// calc transform and add point and flag
2722cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2723cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2724cdf0e10cSrcweir 					}
2725cdf0e10cSrcweir 					break;
2726cdf0e10cSrcweir 				}
2727cdf0e10cSrcweir 
2728cdf0e10cSrcweir 				case 'v' :
2729cdf0e10cSrcweir 				{
2730cdf0e10cSrcweir 					bRelative = true;
2731cdf0e10cSrcweir 				}
2732cdf0e10cSrcweir 				case 'V' :
2733cdf0e10cSrcweir 				{
2734cdf0e10cSrcweir 					nPos++;
2735cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2736cdf0e10cSrcweir 
2737cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2738cdf0e10cSrcweir 					{
2739cdf0e10cSrcweir 						sal_Int32 nX(mnLastX);
2740cdf0e10cSrcweir 						sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2741cdf0e10cSrcweir 
2742cdf0e10cSrcweir 						if(bRelative)
2743cdf0e10cSrcweir 							nY += mnLastY;
2744cdf0e10cSrcweir 
2745cdf0e10cSrcweir 						// set last position
2746cdf0e10cSrcweir 						mnLastY = nY;
2747cdf0e10cSrcweir 
2748cdf0e10cSrcweir 						// calc transform and add point and flag
2749cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2750cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2751cdf0e10cSrcweir 					}
2752cdf0e10cSrcweir 					break;
2753cdf0e10cSrcweir 				}
2754cdf0e10cSrcweir 
2755cdf0e10cSrcweir 				case 's' :
2756cdf0e10cSrcweir 				{
2757cdf0e10cSrcweir 					bRelative = true;
2758cdf0e10cSrcweir 				}
2759cdf0e10cSrcweir 				case 'S' :
2760cdf0e10cSrcweir 				{
2761cdf0e10cSrcweir 					nPos++;
2762cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2763cdf0e10cSrcweir 
2764cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2765cdf0e10cSrcweir 					{
2766cdf0e10cSrcweir 						sal_Int32 nX1;
2767cdf0e10cSrcweir 						sal_Int32 nY1;
2768cdf0e10cSrcweir                         sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2769cdf0e10cSrcweir                         sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2770cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2771cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2772cdf0e10cSrcweir 
2773cdf0e10cSrcweir 						if(bRelative)
2774cdf0e10cSrcweir 						{
2775cdf0e10cSrcweir 							nX2 += mnLastX;
2776cdf0e10cSrcweir 							nY2 += mnLastY;
2777cdf0e10cSrcweir 							nX += mnLastX;
2778cdf0e10cSrcweir 							nY += mnLastY;
2779cdf0e10cSrcweir 						}
2780cdf0e10cSrcweir 
2781cdf0e10cSrcweir 						// set last position
2782cdf0e10cSrcweir 						mnLastX = nX;
2783cdf0e10cSrcweir 						mnLastY = nY;
2784cdf0e10cSrcweir 
2785cdf0e10cSrcweir 						// calc transform for new points
2786cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2787cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2788cdf0e10cSrcweir 
2789cdf0e10cSrcweir 						// one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
2790cdf0e10cSrcweir 						// and the Point X1,Y1 can be constructed by mirroring the point before it.
2791cdf0e10cSrcweir 						nX1 = nX2;
2792cdf0e10cSrcweir 						nY1 = nY2;
2793cdf0e10cSrcweir 						if(nInnerIndex)
2794cdf0e10cSrcweir 						{
2795cdf0e10cSrcweir 							awt::Point aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1];
2796cdf0e10cSrcweir 
2797cdf0e10cSrcweir 							if(nInnerIndex > 1)
2798cdf0e10cSrcweir 							{
2799cdf0e10cSrcweir 								awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2];
2800cdf0e10cSrcweir 								nX1 = aPPrev1.X -(aPPrev2.X - aPPrev1.X);
2801cdf0e10cSrcweir 								nY1 = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y);
2802cdf0e10cSrcweir 							}
2803cdf0e10cSrcweir 
2804cdf0e10cSrcweir 							// set curve point to symmetric
2805cdf0e10cSrcweir 							pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC;
2806cdf0e10cSrcweir 						}
2807cdf0e10cSrcweir 
2808cdf0e10cSrcweir 						// add calculated control point
2809cdf0e10cSrcweir 						Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2810cdf0e10cSrcweir 
2811cdf0e10cSrcweir 						// add new points and set flags
2812cdf0e10cSrcweir 						Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2813cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2814cdf0e10cSrcweir 					}
2815cdf0e10cSrcweir 					break;
2816cdf0e10cSrcweir 				}
2817cdf0e10cSrcweir 
2818cdf0e10cSrcweir 				case 'c' :
2819cdf0e10cSrcweir 				{
2820cdf0e10cSrcweir 					bRelative = true;
2821cdf0e10cSrcweir 				}
2822cdf0e10cSrcweir 				case 'C' :
2823cdf0e10cSrcweir 				{
2824cdf0e10cSrcweir 					nPos++;
2825cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2826cdf0e10cSrcweir 
2827cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2828cdf0e10cSrcweir 					{
2829cdf0e10cSrcweir                         sal_Int32 nX1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2830cdf0e10cSrcweir                         sal_Int32 nY1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2831cdf0e10cSrcweir                         sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2832cdf0e10cSrcweir                         sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2833cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2834cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2835cdf0e10cSrcweir 
2836cdf0e10cSrcweir 						if(bRelative)
2837cdf0e10cSrcweir 						{
2838cdf0e10cSrcweir 							nX1 += mnLastX;
2839cdf0e10cSrcweir 							nY1 += mnLastY;
2840cdf0e10cSrcweir 							nX2 += mnLastX;
2841cdf0e10cSrcweir 							nY2 += mnLastY;
2842cdf0e10cSrcweir 							nX += mnLastX;
2843cdf0e10cSrcweir 							nY += mnLastY;
2844cdf0e10cSrcweir 						}
2845cdf0e10cSrcweir 
2846cdf0e10cSrcweir 						// set last position
2847cdf0e10cSrcweir 						mnLastX = nX;
2848cdf0e10cSrcweir 						mnLastY = nY;
2849cdf0e10cSrcweir 
2850cdf0e10cSrcweir 						// calc transform for new points
2851cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX1, nY1, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2852cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2853cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2854cdf0e10cSrcweir 
2855cdf0e10cSrcweir 						// correct polygon flag for previous point
2856cdf0e10cSrcweir 						Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
2857cdf0e10cSrcweir 
2858cdf0e10cSrcweir 						// add new points and set flags
2859cdf0e10cSrcweir 						Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2860cdf0e10cSrcweir 						Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2861cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2862cdf0e10cSrcweir 					}
2863cdf0e10cSrcweir 					break;
2864cdf0e10cSrcweir 				}
2865cdf0e10cSrcweir 
2866cdf0e10cSrcweir 				// #100617# quadratic beziers are imported as cubic
2867cdf0e10cSrcweir 				case 'q' :
2868cdf0e10cSrcweir 				{
2869cdf0e10cSrcweir 					bRelative = true;
2870cdf0e10cSrcweir 				}
2871cdf0e10cSrcweir 				case 'Q' :
2872cdf0e10cSrcweir 				{
2873cdf0e10cSrcweir 					nPos++;
2874cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2875cdf0e10cSrcweir 
2876cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2877cdf0e10cSrcweir 					{
2878cdf0e10cSrcweir                         sal_Int32 nXX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2879cdf0e10cSrcweir                         sal_Int32 nYY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2880cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2881cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2882cdf0e10cSrcweir 
2883cdf0e10cSrcweir 						if(bRelative)
2884cdf0e10cSrcweir 						{
2885cdf0e10cSrcweir 							nXX += mnLastX;
2886cdf0e10cSrcweir 							nYY += mnLastY;
2887cdf0e10cSrcweir 							nX += mnLastX;
2888cdf0e10cSrcweir 							nY += mnLastY;
2889cdf0e10cSrcweir 						}
2890cdf0e10cSrcweir 
2891cdf0e10cSrcweir 						// set last position
2892cdf0e10cSrcweir 						mnLastX = nX;
2893cdf0e10cSrcweir 						mnLastY = nY;
2894cdf0e10cSrcweir 
2895cdf0e10cSrcweir 						// calc transform for new points
2896cdf0e10cSrcweir 						Imp_PrepareCoorImport(nXX, nYY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2897cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2898cdf0e10cSrcweir 
2899cdf0e10cSrcweir 						// calculate X1,X2
2900cdf0e10cSrcweir 						awt::Point aPPrev1 = (nInnerIndex) ? pNotSoInnerSequence[nInnerIndex-1] : pNotSoInnerSequence[0];
2901cdf0e10cSrcweir 						sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0);
2902cdf0e10cSrcweir 						sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0);
2903cdf0e10cSrcweir 						sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0);
2904cdf0e10cSrcweir 						sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0);
2905cdf0e10cSrcweir 
2906cdf0e10cSrcweir 						// correct polygon flag for previous point
2907cdf0e10cSrcweir 						Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
2908cdf0e10cSrcweir 
2909cdf0e10cSrcweir 						// add new points and set flags
2910cdf0e10cSrcweir 						Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2911cdf0e10cSrcweir 						Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2912cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2913cdf0e10cSrcweir 					}
2914cdf0e10cSrcweir 					break;
2915cdf0e10cSrcweir 				}
2916cdf0e10cSrcweir 
2917cdf0e10cSrcweir 				// #100617# relative quadratic beziers are imported as cubic
2918cdf0e10cSrcweir 				case 't' :
2919cdf0e10cSrcweir 				{
2920cdf0e10cSrcweir 					bRelative = true;
2921cdf0e10cSrcweir 				}
2922cdf0e10cSrcweir 				case 'T' :
2923cdf0e10cSrcweir 				{
2924cdf0e10cSrcweir 					nPos++;
2925cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2926cdf0e10cSrcweir 
2927cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2928cdf0e10cSrcweir 					{
2929cdf0e10cSrcweir 						sal_Int32 nXX;
2930cdf0e10cSrcweir 						sal_Int32 nYY;
2931cdf0e10cSrcweir                         sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2932cdf0e10cSrcweir                         sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv));
2933cdf0e10cSrcweir 
2934cdf0e10cSrcweir 						if(bRelative)
2935cdf0e10cSrcweir 						{
2936cdf0e10cSrcweir 							nX += mnLastX;
2937cdf0e10cSrcweir 							nY += mnLastY;
2938cdf0e10cSrcweir 						}
2939cdf0e10cSrcweir 
2940cdf0e10cSrcweir 						// set last position
2941cdf0e10cSrcweir 						mnLastX = nX;
2942cdf0e10cSrcweir 						mnLastY = nY;
2943cdf0e10cSrcweir 
2944cdf0e10cSrcweir 						// calc transform for new points
2945cdf0e10cSrcweir 						Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate);
2946cdf0e10cSrcweir 
2947cdf0e10cSrcweir 						// one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
2948cdf0e10cSrcweir 						// and the Point X1,Y1 can be constructed by mirroring the point before it.
2949cdf0e10cSrcweir 						nXX = nX;
2950cdf0e10cSrcweir 						nYY = nY;
2951cdf0e10cSrcweir 						awt::Point aPPrev1 = pNotSoInnerSequence[0];
2952cdf0e10cSrcweir 
2953cdf0e10cSrcweir 						if(nInnerIndex)
2954cdf0e10cSrcweir 						{
2955cdf0e10cSrcweir 							aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1];
2956cdf0e10cSrcweir 
2957cdf0e10cSrcweir 							if(nInnerIndex > 1)
2958cdf0e10cSrcweir 							{
2959cdf0e10cSrcweir 								awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2];
2960cdf0e10cSrcweir 								nXX = aPPrev1.X -(aPPrev2.X - aPPrev1.X);
2961cdf0e10cSrcweir 								nYY = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y);
2962cdf0e10cSrcweir 							}
2963cdf0e10cSrcweir 
2964cdf0e10cSrcweir 							// set curve point to smooth here, since length
2965cdf0e10cSrcweir 							// is changed and thus only c1 can be used.
2966cdf0e10cSrcweir 							pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH;
2967cdf0e10cSrcweir 						}
2968cdf0e10cSrcweir 
2969cdf0e10cSrcweir 						// calculate X1,X2
2970cdf0e10cSrcweir 						sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0);
2971cdf0e10cSrcweir 						sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0);
2972cdf0e10cSrcweir 						sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0);
2973cdf0e10cSrcweir 						sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0);
2974cdf0e10cSrcweir 
2975cdf0e10cSrcweir 						// correct polygon flag for previous point
2976cdf0e10cSrcweir 						Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1);
2977cdf0e10cSrcweir 
2978cdf0e10cSrcweir 						// add new points and set flags
2979cdf0e10cSrcweir 						Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2980cdf0e10cSrcweir 						Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL);
2981cdf0e10cSrcweir 						Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH);
2982cdf0e10cSrcweir 					}
2983cdf0e10cSrcweir 					break;
2984cdf0e10cSrcweir 				}
2985cdf0e10cSrcweir 
2986cdf0e10cSrcweir 				// #100617# not yet supported: elliptical arc
2987cdf0e10cSrcweir 				case 'A' :
2988cdf0e10cSrcweir 				case 'a' :
2989cdf0e10cSrcweir 				{
2990cdf0e10cSrcweir 					DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
2991cdf0e10cSrcweir 					nPos++;
2992cdf0e10cSrcweir 					Imp_SkipSpaces(aStr, nPos, nLen);
2993cdf0e10cSrcweir 
2994cdf0e10cSrcweir 					while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos))
2995cdf0e10cSrcweir 					{
2996cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2997cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2998cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
2999cdf0e10cSrcweir 						Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
3000cdf0e10cSrcweir 						Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen);
3001cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
3002cdf0e10cSrcweir 						Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen);
3003cdf0e10cSrcweir 					}
3004cdf0e10cSrcweir 					break;
3005cdf0e10cSrcweir 				}
3006cdf0e10cSrcweir 
3007cdf0e10cSrcweir 				default:
3008cdf0e10cSrcweir 				{
3009cdf0e10cSrcweir 					nPos++;
3010cdf0e10cSrcweir 					DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
3011cdf0e10cSrcweir 					break;
3012cdf0e10cSrcweir 				}
3013cdf0e10cSrcweir 			}
3014cdf0e10cSrcweir 		}
3015cdf0e10cSrcweir 
3016cdf0e10cSrcweir 		// #104076# end-process closed state of last poly
3017cdf0e10cSrcweir 		if(mbIsClosed)
3018cdf0e10cSrcweir 		{
3019cdf0e10cSrcweir 			if(pNotSoInnerSequence)
3020cdf0e10cSrcweir 			{
3021cdf0e10cSrcweir 				// closed: add first point again
3022cdf0e10cSrcweir 				sal_Int32 nX(pNotSoInnerSequence[0].X);
3023cdf0e10cSrcweir 				sal_Int32 nY(pNotSoInnerSequence[0].Y);
3024cdf0e10cSrcweir 				Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
3025cdf0e10cSrcweir 			}
3026cdf0e10cSrcweir 		}
3027cdf0e10cSrcweir 
3028cdf0e10cSrcweir 		// #87202# If it's a curve and it's closed the last point maybe too much
3029cdf0e10cSrcweir 		// and just exported since SVG does not allow special handling of same
3030cdf0e10cSrcweir 		// start and end point, remove this last point.
3031cdf0e10cSrcweir 		// Evtl. correct the last curve flags, too.
3032cdf0e10cSrcweir 		if(IsCurve() && IsClosed())
3033cdf0e10cSrcweir 		{
3034cdf0e10cSrcweir 			// make one more loop over the PolyPolygon
3035cdf0e10cSrcweir 			pOuterSequence = maPoly.getArray();
3036cdf0e10cSrcweir 			pOuterFlags = maFlag.getArray();
3037cdf0e10cSrcweir 			sal_Int32 nOuterCnt(maPoly.getLength());
3038cdf0e10cSrcweir 
3039cdf0e10cSrcweir 			for(sal_Int32 a(0); a < nOuterCnt; a++)
3040cdf0e10cSrcweir 			{
3041cdf0e10cSrcweir 				// get Polygon pointers
3042cdf0e10cSrcweir 				awt::Point* pInnerSequence = pOuterSequence->getArray();
3043cdf0e10cSrcweir 				drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
3044cdf0e10cSrcweir 				sal_Int32 nInnerCnt(pOuterSequence->getLength());
3045cdf0e10cSrcweir 
3046cdf0e10cSrcweir 				while( nInnerCnt >= 2
3047cdf0e10cSrcweir 					&& ((pInnerSequence + (nInnerCnt - 2))->X == (pInnerSequence + (nInnerCnt - 1))->X)
3048cdf0e10cSrcweir 					&& ((pInnerSequence + (nInnerCnt - 2))->Y == (pInnerSequence + (nInnerCnt - 1))->Y)
3049cdf0e10cSrcweir 					&& drawing::PolygonFlags_CONTROL != *(pInnerFlags + (nInnerCnt - 2)))
3050cdf0e10cSrcweir 				{
3051cdf0e10cSrcweir 					// remove last point from array
3052cdf0e10cSrcweir 					pOuterSequence->realloc(nInnerCnt - 1);
3053cdf0e10cSrcweir 					pOuterFlags->realloc(nInnerCnt - 1);
3054cdf0e10cSrcweir 
3055cdf0e10cSrcweir 					// get new pointers
3056cdf0e10cSrcweir 					pInnerSequence = pOuterSequence->getArray();
3057cdf0e10cSrcweir 					pInnerFlags = pOuterFlags->getArray();
3058cdf0e10cSrcweir 					nInnerCnt = pOuterSequence->getLength();
3059cdf0e10cSrcweir 				}
3060cdf0e10cSrcweir 
3061cdf0e10cSrcweir 				// now evtl. correct the last curve flags
3062cdf0e10cSrcweir 				if(nInnerCnt >= 4)
3063cdf0e10cSrcweir 				{
3064cdf0e10cSrcweir 					if(	pInnerSequence->X == (pInnerSequence + (nInnerCnt - 1))->X
3065cdf0e10cSrcweir 						&& pInnerSequence->Y == (pInnerSequence + (nInnerCnt - 1))->Y
3066cdf0e10cSrcweir 						&& drawing::PolygonFlags_CONTROL == *(pInnerFlags + 1)
3067cdf0e10cSrcweir 						&& drawing::PolygonFlags_CONTROL == *(pInnerFlags + (nInnerCnt - 2)))
3068cdf0e10cSrcweir 					{
3069cdf0e10cSrcweir 						awt::Point aPrev = *(pInnerSequence + (nInnerCnt - 2));
3070cdf0e10cSrcweir 						awt::Point aCurr = *pInnerSequence;
3071cdf0e10cSrcweir 						awt::Point aNext = *(pInnerSequence + 1);
3072cdf0e10cSrcweir 						::basegfx::B2DVector aVec1(aPrev.X - aCurr.X, aPrev.Y - aCurr.Y);
3073cdf0e10cSrcweir 						::basegfx::B2DVector aVec2(aNext.X - aCurr.X, aNext.Y - aCurr.Y);
3074cdf0e10cSrcweir 						bool bSameLength(false);
3075cdf0e10cSrcweir 						bool bSameDirection(false);
3076cdf0e10cSrcweir 
3077cdf0e10cSrcweir 						// get vector values
3078cdf0e10cSrcweir 						Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
3079cdf0e10cSrcweir 
3080cdf0e10cSrcweir 						// set correct flag value
3081cdf0e10cSrcweir 						if(bSameDirection)
3082cdf0e10cSrcweir 						{
3083cdf0e10cSrcweir 							if(bSameLength)
3084cdf0e10cSrcweir 							{
3085cdf0e10cSrcweir 								// set to PolygonFlags_SYMMETRIC
3086cdf0e10cSrcweir 								*pInnerFlags = drawing::PolygonFlags_SYMMETRIC;
3087cdf0e10cSrcweir 								*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SYMMETRIC;
3088cdf0e10cSrcweir 							}
3089cdf0e10cSrcweir 							else
3090cdf0e10cSrcweir 							{
3091cdf0e10cSrcweir 								// set to PolygonFlags_SMOOTH
3092cdf0e10cSrcweir 								*pInnerFlags = drawing::PolygonFlags_SMOOTH;
3093cdf0e10cSrcweir 								*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SMOOTH;
3094cdf0e10cSrcweir 							}
3095cdf0e10cSrcweir 						}
3096cdf0e10cSrcweir 						else
3097cdf0e10cSrcweir 						{
3098cdf0e10cSrcweir 							// set to PolygonFlags_NORMAL
3099cdf0e10cSrcweir 							*pInnerFlags = drawing::PolygonFlags_NORMAL;
3100cdf0e10cSrcweir 							*(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_NORMAL;
3101cdf0e10cSrcweir 						}
3102cdf0e10cSrcweir 					}
3103cdf0e10cSrcweir 				}
3104cdf0e10cSrcweir 
3105cdf0e10cSrcweir 				// switch to next Polygon
3106cdf0e10cSrcweir 				pOuterSequence++;
3107cdf0e10cSrcweir 				pOuterFlags++;
3108cdf0e10cSrcweir 			}
3109cdf0e10cSrcweir 		}
3110cdf0e10cSrcweir 	}
3111cdf0e10cSrcweir }
3112cdf0e10cSrcweir 
3113cdf0e10cSrcweir // eof
3114