xref: /trunk/main/xmloff/source/draw/xexptran.cxx (revision b597708ba18998e5b62934c916addb8de3415a8a)
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