xref: /aoo42x/main/xmloff/source/draw/xexptran.cxx (revision 1f882ec4)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include "xexptran.hxx"
27 #include <tools/debug.hxx>
28 #include <rtl/ustrbuf.hxx>
29 #include <xmloff/xmluconv.hxx>
30 #include <tools/gen.hxx>
31 #include <basegfx/vector/b2dvector.hxx>
32 #include <basegfx/matrix/b2dhommatrix.hxx>
33 #include <basegfx/tuple/b3dtuple.hxx>
34 #include <basegfx/matrix/b3dhommatrix.hxx>
35 #include <tools/string.hxx>
36 
37 using ::rtl::OUString;
38 using ::rtl::OUStringBuffer;
39 
40 using namespace ::com::sun::star;
41 
42 //////////////////////////////////////////////////////////////////////////////
43 // Defines
44 
45 #define BORDER_INTEGERS_ARE_EQUAL		(4)
46 
47 //////////////////////////////////////////////////////////////////////////////
48 // Predeclarations
49 
50 void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen);
51 void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection);
52 
53 //////////////////////////////////////////////////////////////////////////////
54 //////////////////////////////////////////////////////////////////////////////
55 // parsing help functions for simple chars
56 void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
57 {
58 	while(rPos < nLen
59 		&& sal_Unicode(' ') == rStr[rPos])
60 		rPos++;
61 }
62 
63 void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
64 {
65 	while(rPos < nLen
66 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos]))
67 		rPos++;
68 }
69 
70 void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
71 {
72 	while(rPos < nLen
73 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos]))
74 		rPos++;
75 }
76 
77 void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
78 {
79 	while(rPos < nLen
80 		&& (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos]))
81 		rPos++;
82 }
83 
84 //////////////////////////////////////////////////////////////////////////////
85 //////////////////////////////////////////////////////////////////////////////
86 // parsing help functions for integer numbers
87 
88 bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
89 {
90 	sal_Unicode aChar(rStr[nPos]);
91 
92 	if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
93 		|| (bSignAllowed && sal_Unicode('+') == aChar)
94 		|| (bSignAllowed && sal_Unicode('-') == aChar)
95 	)
96 		return true;
97 	return false;
98 }
99 
100 bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos)
101 {
102 	sal_Unicode aChar(rStr[nPos]);
103 
104 	if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
105 		|| (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
106 		|| sal_Unicode('%') == aChar
107 	)
108 		return true;
109 	return false;
110 }
111 
112 void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
113 {
114 	bool bSignAllowed(true);
115 
116 	while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed))
117 	{
118 		bSignAllowed = false;
119 		rPos++;
120 	}
121 }
122 
123 void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
124 	const sal_Int32 nLen)
125 {
126 	Imp_SkipNumber(rStr, rPos, nLen);
127 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
128 }
129 
130 // #100617# Allow to skip doubles, too.
131 void Imp_SkipDoubleAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
132 	const sal_Int32 nLen)
133 {
134 	Imp_SkipDouble(rStr, rPos, nLen);
135 	Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
136 }
137 
138 void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue)
139 {
140 	OUStringBuffer sStringBuffer;
141 	SvXMLUnitConverter::convertNumber(sStringBuffer, nValue);
142 	rStr += OUString(sStringBuffer.makeStringAndClear());
143 }
144 
145 void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue)
146 {
147 	const sal_Int32 aLen(rStr.getLength());
148 	if(aLen)
149 		if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0)
150 			rStr += String(sal_Unicode(' '));
151 	Imp_PutNumberChar(rStr, nValue);
152 }
153 
154 //////////////////////////////////////////////////////////////////////////////
155 //////////////////////////////////////////////////////////////////////////////
156 // parsing help functions for double numbers
157 
158 void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32)
159 {
160 	sal_Unicode aChar(rStr[rPos]);
161 
162 	if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
163 		aChar = rStr[++rPos];
164 
165 	while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
166 		|| sal_Unicode('.') == aChar)
167 	{
168 		aChar = rStr[++rPos];
169 	}
170 
171 	if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
172 	{
173 		aChar = rStr[++rPos];
174 
175 		if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
176 			aChar = rStr[++rPos];
177 
178 		while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
179 		{
180 			aChar = rStr[++rPos];
181 		}
182 	}
183 }
184 
185 double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen,
186 	const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
187 {
188 	sal_Unicode aChar(rStr[rPos]);
189 	OUStringBuffer sNumberString;
190 
191 	if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
192 	{
193 		sNumberString.append(rStr[rPos]);
194 		aChar = rStr[++rPos];
195 	}
196 
197 	while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
198 		|| sal_Unicode('.') == aChar)
199 	{
200 		sNumberString.append(rStr[rPos]);
201 		aChar = rStr[++rPos];
202 	}
203 
204 	if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
205 	{
206 		sNumberString.append(rStr[rPos]);
207 		aChar = rStr[++rPos];
208 
209 		if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
210 		{
211 			sNumberString.append(rStr[rPos]);
212 			aChar = rStr[++rPos];
213 		}
214 
215 		while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
216 		{
217 			sNumberString.append(rStr[rPos]);
218 			aChar = rStr[++rPos];
219 		}
220 	}
221 
222 	if(bLookForUnits)
223 	{
224 		Imp_SkipSpaces(rStr, rPos, nLen);
225 		while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
226 			sNumberString.append(rStr[rPos++]);
227 	}
228 
229 	if(sNumberString.getLength())
230 	{
231 		if(bLookForUnits)
232 			rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true);
233 		else
234 			rConv.convertDouble(fRetval, sNumberString.makeStringAndClear());
235 	}
236 
237 	return fRetval;
238 }
239 
240 void Imp_PutDoubleChar(OUString& rStr, double fValue)
241 {
242     OUStringBuffer sStringBuffer;
243     SvXMLUnitConverter::convertDouble(sStringBuffer, fValue);
244     rStr += OUString(sStringBuffer.makeStringAndClear());
245 }
246 
247 void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
248 	bool bConvertUnits = false)
249 {
250 	OUStringBuffer sStringBuffer;
251 
252 	if(bConvertUnits)
253 		rConv.convertDouble(sStringBuffer, fValue, true);
254 	else
255 		rConv.convertDouble(sStringBuffer, fValue);
256 
257 	rStr += OUString(sStringBuffer.makeStringAndClear());
258 }
259 
260 //////////////////////////////////////////////////////////////////////////////
261 //////////////////////////////////////////////////////////////////////////////
262 // base class of all 2D transform objects
263 
264 struct ImpSdXMLExpTransObj2DBase
265 {
266 	sal_uInt16					mnType;
267 	ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
268 	:	mnType(nType) {}
269 };
270 
271 //////////////////////////////////////////////////////////////////////////////
272 // possible object types for 2D
273 
274 #define	IMP_SDXMLEXP_TRANSOBJ2D_ROTATE			0x0000
275 #define	IMP_SDXMLEXP_TRANSOBJ2D_SCALE			0x0001
276 #define	IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE		0x0002
277 #define	IMP_SDXMLEXP_TRANSOBJ2D_SKEWX			0x0003
278 #define	IMP_SDXMLEXP_TRANSOBJ2D_SKEWY			0x0004
279 #define	IMP_SDXMLEXP_TRANSOBJ2D_MATRIX			0x0005
280 
281 //////////////////////////////////////////////////////////////////////////////
282 // classes of objects, different sizes
283 
284 struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
285 {
286 	double						mfRotate;
287 	ImpSdXMLExpTransObj2DRotate(double fVal)
288 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {}
289 };
290 struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
291 {
292 	::basegfx::B2DTuple			maScale;
293 	ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
294 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {}
295 };
296 struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
297 {
298 	::basegfx::B2DTuple			maTranslate;
299 	ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
300 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {}
301 };
302 struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
303 {
304 	double						mfSkewX;
305 	ImpSdXMLExpTransObj2DSkewX(double fVal)
306 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {}
307 };
308 struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
309 {
310 	double						mfSkewY;
311 	ImpSdXMLExpTransObj2DSkewY(double fVal)
312 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {}
313 };
314 struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
315 {
316 	::basegfx::B2DHomMatrix		maMatrix;
317 	ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
318 	:	ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {}
319 };
320 
321 //////////////////////////////////////////////////////////////////////////////
322 //////////////////////////////////////////////////////////////////////////////
323 // delete all entries in list
324 
325 void SdXMLImExTransform2D::EmptyList()
326 {
327     const sal_uInt32 nCount = maList.size();
328 	for(sal_uInt32 a(0L); a < nCount; a++)
329 	{
330 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
331 
332 		switch(pObj->mnType)
333 		{
334 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE		:
335 			{
336 				delete (ImpSdXMLExpTransObj2DRotate*)pObj;
337 				break;
338 			}
339 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
340 			{
341 				delete (ImpSdXMLExpTransObj2DScale*)pObj;
342 				break;
343 			}
344 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
345 			{
346 				delete (ImpSdXMLExpTransObj2DTranslate*)pObj;
347 				break;
348 			}
349 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
350 			{
351 				delete (ImpSdXMLExpTransObj2DSkewX*)pObj;
352 				break;
353 			}
354 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
355 			{
356 				delete (ImpSdXMLExpTransObj2DSkewY*)pObj;
357 				break;
358 			}
359 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX		:
360 			{
361 				delete (ImpSdXMLExpTransObj2DMatrix*)pObj;
362 				break;
363 			}
364 			default :
365 			{
366 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
367 				break;
368 			}
369 		}
370 	}
371 
372 	maList.clear();
373 }
374 
375 //////////////////////////////////////////////////////////////////////////////
376 // add members
377 
378 void SdXMLImExTransform2D::AddRotate(double fNew)
379 {
380 	if(fNew != 0.0)
381 		maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew));
382 }
383 
384 void SdXMLImExTransform2D::AddScale(const ::basegfx::B2DTuple& rNew)
385 {
386 	if(1.0 != rNew.getX() || 1.0 != rNew.getY())
387 		maList.push_back(new ImpSdXMLExpTransObj2DScale(rNew));
388 }
389 
390 void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
391 {
392 	if(!rNew.equalZero())
393 		maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew));
394 }
395 
396 void SdXMLImExTransform2D::AddSkewX(double fNew)
397 {
398 	if(fNew != 0.0)
399 		maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew));
400 }
401 
402 void SdXMLImExTransform2D::AddSkewY(double fNew)
403 {
404 	if(fNew != 0.0)
405 		maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fNew));
406 }
407 
408 void SdXMLImExTransform2D::AddMatrix(const ::basegfx::B2DHomMatrix& rNew)
409 {
410 	if(!rNew.isIdentity())
411 		maList.push_back(new ImpSdXMLExpTransObj2DMatrix(rNew));
412 }
413 
414 //////////////////////////////////////////////////////////////////////////////
415 // gen string for export
416 const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv)
417 {
418 	OUString aNewString;
419 	OUString aClosingBrace(sal_Unicode(')'));
420 	OUString aEmptySpace(sal_Unicode(' '));
421 
422 	const sal_uInt32 nCount = maList.size();
423 	for(sal_uInt32 a(0L); a < nCount; a++)
424 	{
425 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
426 		switch(pObj->mnType)
427 		{
428 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE	:
429 			{
430 				aNewString += OUString::createFromAscii("rotate (");
431 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate);
432 				aNewString += aClosingBrace;
433 				break;
434 			}
435 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
436 			{
437 				aNewString += OUString::createFromAscii("scale (");
438 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX());
439 				aNewString += aEmptySpace;
440 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY());
441 				aNewString += aClosingBrace;
442 				break;
443 			}
444 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
445 			{
446 				aNewString += OUString::createFromAscii("translate (");
447 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true);
448 				aNewString += aEmptySpace;
449 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true);
450 				aNewString += aClosingBrace;
451 				break;
452 			}
453 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
454 			{
455 				aNewString += OUString::createFromAscii("skewX (");
456 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX);
457 				aNewString += aClosingBrace;
458 				break;
459 			}
460 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
461 			{
462 				aNewString += OUString::createFromAscii("skewY (");
463 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY);
464 				aNewString += aClosingBrace;
465 				break;
466 			}
467 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX	:
468 			{
469 				aNewString += OUString::createFromAscii("matrix (");
470 
471 				// a
472 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0));
473 				aNewString += aEmptySpace;
474 
475 				// b
476 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0));
477 				aNewString += aEmptySpace;
478 
479 				// c
480 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1));
481 				aNewString += aEmptySpace;
482 
483 				// d
484 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1));
485 				aNewString += aEmptySpace;
486 
487 				// e
488 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true);
489 				aNewString += aEmptySpace;
490 
491 				// f
492 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true);
493 
494 				aNewString += aClosingBrace;
495 				break;
496 			}
497 			default :
498 			{
499 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
500 				break;
501 			}
502 		}
503 
504 		// if not the last entry, add one space to next tag
505 		if(a + 1UL != maList.size())
506 		{
507 			aNewString += aEmptySpace;
508 		}
509 	}
510 
511 	// fill string form OUString
512 	msString = aNewString;
513 
514 	return msString;
515 }
516 
517 //////////////////////////////////////////////////////////////////////////////
518 // for Import: constructor with string, parses it and generates entries
519 SdXMLImExTransform2D::SdXMLImExTransform2D(const OUString& rNew, const SvXMLUnitConverter& rConv)
520 {
521 	SetString(rNew, rConv);
522 }
523 
524 //////////////////////////////////////////////////////////////////////////////
525 // sets new string, parses it and generates entries
526 void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
527 {
528 	msString = rNew;
529 	EmptyList();
530 
531 	if(msString.getLength())
532 	{
533 		const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
534 		const sal_Int32 nLen(aStr.getLength());
535 
536 		const OUString aString_rotate(OUString::createFromAscii("rotate"));
537 		const OUString aString_scale(OUString::createFromAscii("scale"));
538 		const OUString aString_translate(OUString::createFromAscii("translate"));
539 		const OUString aString_skewX(OUString::createFromAscii("skewX"));
540 		const OUString aString_skewY(OUString::createFromAscii("skewY"));
541 		const OUString aString_matrix(OUString::createFromAscii("matrix"));
542 
543 		sal_Int32 nPos(0);
544 
545 		while(nPos < nLen)
546 		{
547 			// skip spaces
548 			Imp_SkipSpaces(aStr, nPos, nLen);
549 
550 			// look for tag
551 			if(nPos < nLen)
552 			{
553 				if(nPos == aStr.indexOf(aString_rotate, nPos))
554 				{
555 					double fValue(0.0);
556 					nPos += 6;
557 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
558 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
559 					if(fValue != 0.0)
560 						maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue));
561 
562 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
563 				}
564 				else if(nPos == aStr.indexOf(aString_scale, nPos))
565 				{
566 					::basegfx::B2DTuple aValue(1.0, 1.0);
567 					nPos += 5;
568 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
569 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
570 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
571 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
572 
573 					if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
574 						maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue));
575 
576 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
577 				}
578 				else if(nPos == aStr.indexOf(aString_translate, nPos))
579 				{
580 					::basegfx::B2DTuple aValue;
581 					nPos += 9;
582 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
583 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
584 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
585 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
586 
587 					if(!aValue.equalZero())
588 						maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue));
589 
590 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
591 				}
592 				else if(nPos == aStr.indexOf(aString_skewX, nPos))
593 				{
594 					double fValue(0.0);
595 					nPos += 5;
596 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
597 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
598 					if(fValue != 0.0)
599 						maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue));
600 
601 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
602 				}
603 				else if(nPos == aStr.indexOf(aString_skewY, nPos))
604 				{
605 					double fValue(0.0);
606 					nPos += 5;
607 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
608 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
609 					if(fValue != 0.0)
610 						maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue));
611 
612 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
613 				}
614 				else if(nPos == aStr.indexOf(aString_matrix, nPos))
615 				{
616 					::basegfx::B2DHomMatrix aValue;
617 
618 					nPos += 6;
619 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
620 
621 					// a
622 					aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
623 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
624 
625 					// b
626 					aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
627 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
628 
629 					// c
630 					aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
631 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
632 
633 					// d
634 					aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
635 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
636 
637 					// e
638 					aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
639 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
640 
641 					// f
642 					aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
643 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
644 
645 					if(!aValue.isIdentity())
646 						maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue));
647 
648 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
649 				}
650 				else
651 				{
652 					nPos++;
653 				}
654 			}
655 		}
656 	}
657 }
658 
659 void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans)
660 {
661 	rFullTrans.identity();
662 
663 	const sal_uInt32 nCount = maList.size();
664 	for(sal_uInt32 a(0L); a < nCount; a++)
665 	{
666 		ImpSdXMLExpTransObj2DBase* pObj = maList[a];
667 		switch(pObj->mnType)
668 		{
669 			case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE		:
670 			{
671                 // #i78696#
672                 // mfRotate is mathematically wrong oriented since we export/import the angle
673                 // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
674                 // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
675                 // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
676                 // to mirror the value here
677 				rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0);
678 				break;
679 			}
680 			case IMP_SDXMLEXP_TRANSOBJ2D_SCALE		:
681 			{
682 				const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale;
683 				rFullTrans.scale(rScale.getX(), rScale.getY());
684 				break;
685 			}
686 			case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE	:
687 			{
688 				const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate;
689 				rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
690 				break;
691 			}
692 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX		:
693 			{
694 				rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX));
695 				break;
696 			}
697 			case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY		:
698 			{
699 				rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY));
700 				break;
701 			}
702 			case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX		:
703 			{
704 				rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix;
705 				break;
706 			}
707 			default :
708 			{
709 				DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
710 				break;
711 			}
712 		}
713 	}
714 }
715 
716 //////////////////////////////////////////////////////////////////////////////
717 //////////////////////////////////////////////////////////////////////////////
718 // base class of all 3D transform objects
719 
720 struct ImpSdXMLExpTransObj3DBase
721 {
722 	sal_uInt16					mnType;
723 	ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
724 	:	mnType(nType) {}
725 };
726 
727 //////////////////////////////////////////////////////////////////////////////
728 // possible object types for 3D
729 
730 #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X		0x0000
731 #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y		0x0001
732 #define	IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z		0x0002
733 #define	IMP_SDXMLEXP_TRANSOBJ3D_SCALE			0x0003
734 #define	IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE		0x0004
735 #define	IMP_SDXMLEXP_TRANSOBJ3D_MATRIX			0x0005
736 
737 //////////////////////////////////////////////////////////////////////////////
738 // classes of objects, different sizes
739 
740 struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
741 {
742 	double						mfRotateX;
743 	ImpSdXMLExpTransObj3DRotateX(double fVal)
744 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {}
745 };
746 struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
747 {
748 	double						mfRotateY;
749 	ImpSdXMLExpTransObj3DRotateY(double fVal)
750 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {}
751 };
752 struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
753 {
754 	double						mfRotateZ;
755 	ImpSdXMLExpTransObj3DRotateZ(double fVal)
756 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {}
757 };
758 struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
759 {
760 	::basegfx::B3DTuple			maScale;
761 	ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
762 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {}
763 };
764 struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
765 {
766 	::basegfx::B3DTuple			maTranslate;
767 	ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
768 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {}
769 };
770 struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
771 {
772 	::basegfx::B3DHomMatrix		maMatrix;
773 	ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
774 	:	ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {}
775 };
776 
777 //////////////////////////////////////////////////////////////////////////////
778 //////////////////////////////////////////////////////////////////////////////
779 // delete all entries in list
780 
781 void SdXMLImExTransform3D::EmptyList()
782 {
783 	const sal_uInt32 nCount = maList.size();
784 	for(sal_uInt32 a(0L); a < nCount; a++)
785 	{
786 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
787 
788 		switch(pObj->mnType)
789 		{
790 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
791 			{
792 				delete (ImpSdXMLExpTransObj3DRotateX*)pObj;
793 				break;
794 			}
795 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
796 			{
797 				delete (ImpSdXMLExpTransObj3DRotateY*)pObj;
798 				break;
799 			}
800 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
801 			{
802 				delete (ImpSdXMLExpTransObj3DRotateZ*)pObj;
803 				break;
804 			}
805 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
806 			{
807 				delete (ImpSdXMLExpTransObj3DScale*)pObj;
808 				break;
809 			}
810 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
811 			{
812 				delete (ImpSdXMLExpTransObj3DTranslate*)pObj;
813 				break;
814 			}
815 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX		:
816 			{
817 				delete (ImpSdXMLExpTransObj3DMatrix*)pObj;
818 				break;
819 			}
820 			default :
821 			{
822 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
823 				break;
824 			}
825 		}
826 	}
827 
828 	maList.clear();
829 }
830 
831 //////////////////////////////////////////////////////////////////////////////
832 // add members
833 
834 void SdXMLImExTransform3D::AddRotateX(double fNew)
835 {
836 	if(fNew != 0.0)
837 		maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fNew));
838 }
839 
840 void SdXMLImExTransform3D::AddRotateY(double fNew)
841 {
842 	if(fNew != 0.0)
843 		maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fNew));
844 }
845 
846 void SdXMLImExTransform3D::AddRotateZ(double fNew)
847 {
848 	if(fNew != 0.0)
849 		maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fNew));
850 }
851 
852 void SdXMLImExTransform3D::AddScale(const ::basegfx::B3DTuple& rNew)
853 {
854 	if(1.0 != rNew.getX() || 1.0 != rNew.getY() || 1.0 != rNew.getZ())
855 		maList.push_back(new ImpSdXMLExpTransObj3DScale(rNew));
856 }
857 
858 void SdXMLImExTransform3D::AddTranslate(const ::basegfx::B3DTuple& rNew)
859 {
860 	if(!rNew.equalZero())
861 		maList.push_back(new ImpSdXMLExpTransObj3DTranslate(rNew));
862 }
863 
864 void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
865 {
866 	if(!rNew.isIdentity())
867 		maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew));
868 }
869 
870 void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
871 {
872 	::basegfx::B3DHomMatrix aExportMatrix;
873 
874 	aExportMatrix.set(0, 0, xHomMat.Line1.Column1);
875 	aExportMatrix.set(0, 1, xHomMat.Line1.Column2);
876 	aExportMatrix.set(0, 2, xHomMat.Line1.Column3);
877 	aExportMatrix.set(0, 3, xHomMat.Line1.Column4);
878 	aExportMatrix.set(1, 0, xHomMat.Line2.Column1);
879 	aExportMatrix.set(1, 1, xHomMat.Line2.Column2);
880 	aExportMatrix.set(1, 2, xHomMat.Line2.Column3);
881 	aExportMatrix.set(1, 3, xHomMat.Line2.Column4);
882 	aExportMatrix.set(2, 0, xHomMat.Line3.Column1);
883 	aExportMatrix.set(2, 1, xHomMat.Line3.Column2);
884 	aExportMatrix.set(2, 2, xHomMat.Line3.Column3);
885 	aExportMatrix.set(2, 3, xHomMat.Line3.Column4);
886 
887 	AddMatrix(aExportMatrix);
888 }
889 
890 //////////////////////////////////////////////////////////////////////////////
891 // gen string for export
892 const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv)
893 {
894 	OUString aNewString;
895 	OUString aClosingBrace(sal_Unicode(')'));
896 	OUString aEmptySpace(sal_Unicode(' '));
897 
898 	const sal_uInt32 nCount = maList.size();
899 	for(sal_uInt32 a(0L); a < nCount; a++)
900 	{
901 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
902 		switch(pObj->mnType)
903 		{
904 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
905 			{
906 				aNewString += OUString::createFromAscii("rotatex (");
907 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX);
908 				aNewString += aClosingBrace;
909 				break;
910 			}
911 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
912 			{
913 				aNewString += OUString::createFromAscii("rotatey (");
914 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY);
915 				aNewString += aClosingBrace;
916 				break;
917 			}
918 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
919 			{
920 				aNewString += OUString::createFromAscii("rotatez (");
921 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
922 				aNewString += aClosingBrace;
923 				break;
924 			}
925 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
926 			{
927 				aNewString += OUString::createFromAscii("scale (");
928 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX());
929 				aNewString += aEmptySpace;
930 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY());
931 				aNewString += aEmptySpace;
932 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ());
933 				aNewString += aClosingBrace;
934 				break;
935 			}
936 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
937 			{
938 				aNewString += OUString::createFromAscii("translate (");
939 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true);
940 				aNewString += aEmptySpace;
941 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true);
942 				aNewString += aEmptySpace;
943 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true);
944 				aNewString += aClosingBrace;
945 				break;
946 			}
947 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX	:
948 			{
949 				aNewString += OUString::createFromAscii("matrix (");
950 
951 				// a
952 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0));
953 				aNewString += aEmptySpace;
954 
955 				// b
956 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0));
957 				aNewString += aEmptySpace;
958 
959 				// c
960 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0));
961 				aNewString += aEmptySpace;
962 
963 				// d
964 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1));
965 				aNewString += aEmptySpace;
966 
967 				// e
968 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1));
969 				aNewString += aEmptySpace;
970 
971 				// f
972 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1));
973 				aNewString += aEmptySpace;
974 
975 				// g
976 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2));
977 				aNewString += aEmptySpace;
978 
979 				// h
980 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2));
981 				aNewString += aEmptySpace;
982 
983 				// i
984 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2));
985 				aNewString += aEmptySpace;
986 
987 				// j
988 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true);
989 				aNewString += aEmptySpace;
990 
991 				// k
992 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true);
993 				aNewString += aEmptySpace;
994 
995 				// l
996 				Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true);
997 
998 				aNewString += aClosingBrace;
999 				break;
1000 			}
1001 			default :
1002 			{
1003 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
1004 				break;
1005 			}
1006 		}
1007 
1008 		// if not the last entry, add one space to next tag
1009 		if(a + 1UL != maList.size())
1010 		{
1011 			aNewString += aEmptySpace;
1012 		}
1013 	}
1014 
1015 	// fill string form OUString
1016 	msString = aNewString;
1017 
1018 	return msString;
1019 }
1020 
1021 //////////////////////////////////////////////////////////////////////////////
1022 // for Import: constructor with string, parses it and generates entries
1023 SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv)
1024 {
1025 	SetString(rNew, rConv);
1026 }
1027 
1028 //////////////////////////////////////////////////////////////////////////////
1029 // sets new string, parses it and generates entries
1030 void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
1031 {
1032 	msString = rNew;
1033 	EmptyList();
1034 
1035 	if(msString.getLength())
1036 	{
1037 		const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1038 		const sal_Int32 nLen(aStr.getLength());
1039 
1040 		const OUString aString_rotatex(OUString::createFromAscii("rotatex"));
1041 		const OUString aString_rotatey(OUString::createFromAscii("rotatey"));
1042 		const OUString aString_rotatez(OUString::createFromAscii("rotatez"));
1043 		const OUString aString_scale(OUString::createFromAscii("scale"));
1044 		const OUString aString_translate(OUString::createFromAscii("translate"));
1045 		const OUString aString_matrix(OUString::createFromAscii("matrix"));
1046 
1047 		sal_Int32 nPos(0);
1048 
1049 		while(nPos < nLen)
1050 		{
1051 			// skip spaces
1052 			Imp_SkipSpaces(aStr, nPos, nLen);
1053 
1054 			// look for tag
1055 			if(nPos < nLen)
1056 			{
1057 				if(nPos == aStr.indexOf(aString_rotatex, nPos))
1058 				{
1059 					double fValue(0.0);
1060 
1061 					nPos += 7;
1062 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1063 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1064 					if(fValue != 0.0)
1065 						maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue));
1066 
1067 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1068 				}
1069 				else if(nPos == aStr.indexOf(aString_rotatey, nPos))
1070 				{
1071 					double fValue(0.0);
1072 
1073 					nPos += 7;
1074 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1075 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1076 					if(fValue != 0.0)
1077 						maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue));
1078 
1079 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1080 				}
1081 				else if(nPos == aStr.indexOf(aString_rotatez, nPos))
1082 				{
1083 					double fValue(0.0);
1084 
1085 					nPos += 7;
1086 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1087 					fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1088 					if(fValue != 0.0)
1089 						maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue));
1090 
1091 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1092 				}
1093 				else if(nPos == aStr.indexOf(aString_scale, nPos))
1094 				{
1095 					::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
1096 
1097 					nPos += 5;
1098 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1099 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
1100 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1101 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
1102 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1103 					aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
1104 
1105 					if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
1106 						maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue));
1107 
1108 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1109 				}
1110 				else if(nPos == aStr.indexOf(aString_translate, nPos))
1111 				{
1112 					::basegfx::B3DTuple aValue;
1113 
1114 					nPos += 9;
1115 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1116 					aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
1117 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1118 					aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
1119 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1120 					aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
1121 
1122 					if(!aValue.equalZero())
1123 						maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue));
1124 
1125 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1126 				}
1127 				else if(nPos == aStr.indexOf(aString_matrix, nPos))
1128 				{
1129 					::basegfx::B3DHomMatrix aValue;
1130 
1131 					nPos += 6;
1132 					Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1133 
1134 					// a
1135 					aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
1136 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1137 
1138 					// b
1139 					aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
1140 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1141 
1142 					// c
1143 					aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
1144 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1145 
1146 					// d
1147 					aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
1148 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1149 
1150 					// e
1151 					aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
1152 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1153 
1154 					// f
1155 					aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
1156 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1157 
1158 					// g
1159 					aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
1160 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1161 
1162 					// h
1163 					aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
1164 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1165 
1166 					// i
1167 					aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
1168 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1169 
1170 					// j
1171 					aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
1172 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1173 
1174 					// k
1175 					aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
1176 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1177 
1178 					// l
1179 					aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
1180 					Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1181 
1182 					if(!aValue.isIdentity())
1183 						maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue));
1184 
1185 					Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1186 				}
1187 				else
1188 				{
1189 					nPos++;
1190 				}
1191 			}
1192 		}
1193 	}
1194 }
1195 
1196 bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat)
1197 {
1198 	::basegfx::B3DHomMatrix aFullTransform;
1199 	GetFullTransform(aFullTransform);
1200 
1201 	if(!aFullTransform.isIdentity())
1202 	{
1203 		xHomMat.Line1.Column1 = aFullTransform.get(0, 0);
1204 		xHomMat.Line1.Column2 = aFullTransform.get(0, 1);
1205 		xHomMat.Line1.Column3 = aFullTransform.get(0, 2);
1206 		xHomMat.Line1.Column4 = aFullTransform.get(0, 3);
1207 
1208 		xHomMat.Line2.Column1 = aFullTransform.get(1, 0);
1209 		xHomMat.Line2.Column2 = aFullTransform.get(1, 1);
1210 		xHomMat.Line2.Column3 = aFullTransform.get(1, 2);
1211 		xHomMat.Line2.Column4 = aFullTransform.get(1, 3);
1212 
1213 		xHomMat.Line3.Column1 = aFullTransform.get(2, 0);
1214 		xHomMat.Line3.Column2 = aFullTransform.get(2, 1);
1215 		xHomMat.Line3.Column3 = aFullTransform.get(2, 2);
1216 		xHomMat.Line3.Column4 = aFullTransform.get(2, 3);
1217 
1218 		xHomMat.Line4.Column1 = aFullTransform.get(3, 0);
1219 		xHomMat.Line4.Column2 = aFullTransform.get(3, 1);
1220 		xHomMat.Line4.Column3 = aFullTransform.get(3, 2);
1221 		xHomMat.Line4.Column4 = aFullTransform.get(3, 3);
1222 
1223 		return true;
1224 	}
1225 
1226 	return false;
1227 }
1228 
1229 void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
1230 {
1231 	rFullTrans.identity();
1232 
1233 	const sal_uInt32 nCount = maList.size();
1234 	for(sal_uInt32 a(0L); a < nCount; a++)
1235 	{
1236 		ImpSdXMLExpTransObj3DBase* pObj = maList[a];
1237 		switch(pObj->mnType)
1238 		{
1239 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X	:
1240 			{
1241 				rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0);
1242 				break;
1243 			}
1244 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y	:
1245 			{
1246 				rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0);
1247 				break;
1248 			}
1249 			case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z	:
1250 			{
1251 				rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
1252 				break;
1253 			}
1254 			case IMP_SDXMLEXP_TRANSOBJ3D_SCALE		:
1255 			{
1256 				const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale;
1257 				rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
1258 				break;
1259 			}
1260 			case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE	:
1261 			{
1262 				const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate;
1263 				rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
1264 				break;
1265 			}
1266 			case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX		:
1267 			{
1268 				rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix;
1269 				break;
1270 			}
1271 			default :
1272 			{
1273 				DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
1274 				break;
1275 			}
1276 		}
1277 	}
1278 }
1279 
1280 //////////////////////////////////////////////////////////////////////////////
1281 //////////////////////////////////////////////////////////////////////////////
1282 
1283 SdXMLImExViewBox::SdXMLImExViewBox(double fX, double fY, double fW, double fH)
1284 :	mfX( fX ),
1285     mfY( fY ),
1286     mfW( fW ),
1287     mfH( fH )
1288 {
1289 }
1290 
1291 // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
1292 SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
1293 :	msString(rNew),
1294     mfX( 0.0 ),
1295     mfY( 0.0 ),
1296     mfW( 1000.0 ),
1297     mfH( 1000.0 )
1298 {
1299     if(msString.getLength())
1300     {
1301         const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1302         const sal_Int32 nLen(aStr.getLength());
1303         sal_Int32 nPos(0);
1304 
1305         // skip starting spaces
1306         Imp_SkipSpaces(aStr, nPos, nLen);
1307 
1308         // get mX, #100617# be prepared for doubles
1309         mfX = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfX);
1310 
1311         // skip spaces and commas
1312         Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1313 
1314         // get mY, #100617# be prepared for doubles
1315         mfY = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfY);
1316 
1317         // skip spaces and commas
1318         Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1319 
1320         // get mW, #100617# be prepared for doubles
1321         mfW = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfW);
1322 
1323         // skip spaces and commas
1324         Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1325 
1326         // get mH, #100617# be prepared for doubles
1327         mfH = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfH);
1328     }
1329 }
1330 
1331 const OUString& SdXMLImExViewBox::GetExportString()
1332 {
1333     OUString aNewString;
1334     OUString aEmptySpace(sal_Unicode(' '));
1335 
1336     Imp_PutDoubleChar(aNewString, mfX);
1337     aNewString += aEmptySpace;
1338 
1339     Imp_PutDoubleChar(aNewString, mfY);
1340     aNewString += aEmptySpace;
1341 
1342     Imp_PutDoubleChar(aNewString, mfW);
1343     aNewString += aEmptySpace;
1344 
1345     Imp_PutDoubleChar(aNewString, mfH);
1346 
1347     // set new string
1348     msString = aNewString;
1349 
1350     return msString;
1351 }
1352 
1353 // eof
1354