1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <string_view>
25 #include <xexptran.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <osl/diagnose.h>
28 #include <sax/tools/converter.hxx>
29 #include <xmloff/xmluconv.hxx>
30 #include <basegfx/matrix/b2dhommatrix.hxx>
31 #include <basegfx/tuple/b2dtuple.hxx>
32 #include <basegfx/tuple/b3dtuple.hxx>
33 #include <basegfx/matrix/b3dhommatrix.hxx>
34 #include <basegfx/numeric/ftools.hxx>
35 #include <basegfx/matrix/b3dhommatrixtools.hxx>
37 using namespace ::com::sun::star
;
39 // parsing help functions for simple chars
40 static void Imp_SkipSpaces(std::u16string_view rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
47 static void Imp_SkipSpacesAndOpeningBraces(std::u16string_view rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
50 && (' ' == rStr
[rPos
] || '(' == rStr
[rPos
]))
54 static void Imp_SkipSpacesAndCommas(std::u16string_view rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
57 && (' ' == rStr
[rPos
] || ',' == rStr
[rPos
]))
61 static void Imp_SkipSpacesAndClosingBraces(std::u16string_view rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
64 && (' ' == rStr
[rPos
] || ')' == rStr
[rPos
]))
68 // parsing help functions for integer numbers
70 static bool Imp_IsOnUnitChar(std::u16string_view rStr
, const sal_Int32 nPos
)
72 sal_Unicode
aChar(rStr
[nPos
]);
74 return ('a' <= aChar
&& 'z' >= aChar
)
75 || ('A' <= aChar
&& 'Z' >= aChar
)
79 static double Imp_GetDoubleChar(std::u16string_view rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
,
80 const SvXMLUnitConverter
& rConv
, double fRetval
, bool bLookForUnits
= false)
82 sal_Unicode
aChar(rStr
[rPos
]);
83 OUStringBuffer
sNumberString(32);
85 if('+' == aChar
|| '-' == aChar
)
87 sNumberString
.append(rStr
[rPos
]);
89 aChar
= rPos
>= nLen
? 0 : rStr
[rPos
];
92 while(('0' <= aChar
&& '9' >= aChar
)
95 sNumberString
.append(rStr
[rPos
]);
97 aChar
= rPos
>= nLen
? 0 : rStr
[rPos
];
100 if('e' == aChar
|| 'E' == aChar
)
102 sNumberString
.append(rStr
[rPos
]);
104 aChar
= rPos
>= nLen
? 0 : rStr
[rPos
];
106 if('+' == aChar
|| '-' == aChar
)
108 sNumberString
.append(rStr
[rPos
]);
110 aChar
= rPos
>= nLen
? 0 : rStr
[rPos
];
113 while('0' <= aChar
&& '9' >= aChar
)
115 sNumberString
.append(rStr
[rPos
]);
117 aChar
= rPos
>= nLen
? 0 : rStr
[rPos
];
123 Imp_SkipSpaces(rStr
, rPos
, nLen
);
124 while(rPos
< nLen
&& Imp_IsOnUnitChar(rStr
, rPos
))
125 sNumberString
.append(rStr
[rPos
++]);
128 if(!sNumberString
.isEmpty())
131 rConv
.convertDouble(fRetval
, sNumberString
);
134 ::sax::Converter::convertDouble(fRetval
, sNumberString
);
141 static void Imp_PutDoubleChar(OUString
& rStr
, double fValue
)
143 OUStringBuffer sStringBuffer
;
144 ::sax::Converter::convertDouble(sStringBuffer
, fValue
);
145 rStr
+= sStringBuffer
;
148 static void Imp_PutDoubleChar(OUStringBuffer
& rStr
, const SvXMLUnitConverter
& rConv
, double fValue
,
149 bool bConvertUnits
= false)
151 OUStringBuffer sStringBuffer
;
154 rConv
.convertDouble(sStringBuffer
, fValue
);
157 ::sax::Converter::convertDouble(sStringBuffer
, fValue
);
160 rStr
.append(sStringBuffer
);
163 // base class of all 2D transform objects
165 struct ImpSdXMLExpTransObj2DBase
168 explicit ImpSdXMLExpTransObj2DBase(sal_uInt16 nType
)
172 // possible object types for 2D
174 #define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000
175 #define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001
176 #define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002
177 #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003
178 #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004
179 #define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005
181 // classes of objects, different sizes
185 struct ImpSdXMLExpTransObj2DRotate
: public ImpSdXMLExpTransObj2DBase
188 explicit ImpSdXMLExpTransObj2DRotate(double fVal
)
189 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
), mfRotate(fVal
) {}
191 struct ImpSdXMLExpTransObj2DScale
: public ImpSdXMLExpTransObj2DBase
193 ::basegfx::B2DTuple maScale
;
194 explicit ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple
& rNew
)
195 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE
), maScale(rNew
) {}
197 struct ImpSdXMLExpTransObj2DTranslate
: public ImpSdXMLExpTransObj2DBase
199 ::basegfx::B2DTuple maTranslate
;
200 explicit ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple
& rNew
)
201 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
), maTranslate(rNew
) {}
203 struct ImpSdXMLExpTransObj2DSkewX
: public ImpSdXMLExpTransObj2DBase
206 explicit ImpSdXMLExpTransObj2DSkewX(double fVal
)
207 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
), mfSkewX(fVal
) {}
209 struct ImpSdXMLExpTransObj2DSkewY
: public ImpSdXMLExpTransObj2DBase
212 explicit ImpSdXMLExpTransObj2DSkewY(double fVal
)
213 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
), mfSkewY(fVal
) {}
215 struct ImpSdXMLExpTransObj2DMatrix
: public ImpSdXMLExpTransObj2DBase
217 ::basegfx::B2DHomMatrix maMatrix
;
218 explicit ImpSdXMLExpTransObj2DMatrix(::basegfx::B2DHomMatrix aNew
)
219 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
), maMatrix(std::move(aNew
)) {}
226 void SdXMLImExTransform2D::AddRotate(double fNew
)
229 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DRotate
>(fNew
));
232 void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple
& rNew
)
234 if(!rNew
.equalZero())
235 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DTranslate
>(rNew
));
238 void SdXMLImExTransform2D::AddSkewX(double fNew
)
241 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DSkewX
>(fNew
));
244 // gen string for export
245 const OUString
& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter
& rConv
)
247 OUStringBuffer aNewString
;
248 OUString
aClosingBrace(")");
249 OUString
aEmptySpace(" ");
251 const sal_uInt32 nCount
= maList
.size();
252 for(sal_uInt32
a(0); a
< nCount
; a
++)
254 ImpSdXMLExpTransObj2DBase
* pObj
= maList
[a
].get();
257 case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
:
259 aNewString
.append("rotate (");
260 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DRotate
*>(pObj
)->mfRotate
);
261 aNewString
.append(aClosingBrace
);
264 case IMP_SDXMLEXP_TRANSOBJ2D_SCALE
:
266 aNewString
.append("scale (");
267 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DScale
*>(pObj
)->maScale
.getX());
268 aNewString
.append(aEmptySpace
);
269 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DScale
*>(pObj
)->maScale
.getY());
270 aNewString
.append(aClosingBrace
);
273 case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
:
275 aNewString
.append("translate (");
276 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DTranslate
*>(pObj
)->maTranslate
.getX(), true);
277 aNewString
.append(aEmptySpace
);
278 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DTranslate
*>(pObj
)->maTranslate
.getY(), true);
279 aNewString
.append(aClosingBrace
);
282 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
:
284 aNewString
.append("skewX (");
285 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DSkewX
*>(pObj
)->mfSkewX
);
286 aNewString
.append(aClosingBrace
);
289 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
:
291 aNewString
.append("skewY (");
292 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DSkewY
*>(pObj
)->mfSkewY
);
293 aNewString
.append(aClosingBrace
);
296 case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
:
298 aNewString
.append("matrix (");
301 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(0, 0));
302 aNewString
.append(aEmptySpace
);
305 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(1, 0));
306 aNewString
.append(aEmptySpace
);
309 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(0, 1));
310 aNewString
.append(aEmptySpace
);
313 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(1, 1));
314 aNewString
.append(aEmptySpace
);
317 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(0, 2), true);
318 aNewString
.append(aEmptySpace
);
321 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
.get(1, 2), true);
323 aNewString
.append(aClosingBrace
);
328 OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
333 // if not the last entry, add one space to next tag
334 if(a
+ 1 != maList
.size())
336 aNewString
.append(aEmptySpace
);
340 // fill string form OUString
341 msString
= aNewString
.makeStringAndClear();
346 // sets new string, parses it and generates entries
347 void SdXMLImExTransform2D::SetString(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
352 if(msString
.isEmpty())
355 const OUString aStr
= msString
;
356 const sal_Int32
nLen(aStr
.getLength());
358 static constexpr OUStringLiteral
aString_rotate( u
"rotate" );
359 static constexpr OUStringLiteral
aString_scale( u
"scale" );
360 static constexpr OUStringLiteral
aString_translate( u
"translate" );
361 static constexpr OUStringLiteral
aString_skewX( u
"skewX" );
362 static constexpr OUStringLiteral
aString_skewY( u
"skewY" );
363 static constexpr OUStringLiteral
aString_matrix( u
"matrix" );
370 Imp_SkipSpaces(aStr
, nPos
, nLen
);
375 if(nPos
== aStr
.indexOf(aString_rotate
, nPos
))
379 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
380 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
382 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DRotate
>(fValue
));
384 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
386 else if(nPos
== aStr
.indexOf(aString_scale
, nPos
))
388 ::basegfx::B2DTuple
aValue(1.0, 1.0);
390 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
391 aValue
.setX(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getX()));
392 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
393 aValue
.setY(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getY()));
395 if(aValue
.getX() != 1.0 || aValue
.getY() != 1.0)
396 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DScale
>(aValue
));
398 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
400 else if(nPos
== aStr
.indexOf(aString_translate
, nPos
))
402 ::basegfx::B2DTuple aValue
;
404 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
405 aValue
.setX(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getX(), true));
406 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
407 aValue
.setY(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getY(), true));
409 if(!aValue
.equalZero())
410 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DTranslate
>(aValue
));
412 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
414 else if(nPos
== aStr
.indexOf(aString_skewX
, nPos
))
418 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
419 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
421 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DSkewX
>(fValue
));
423 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
425 else if(nPos
== aStr
.indexOf(aString_skewY
, nPos
))
429 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
430 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
432 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DSkewY
>(fValue
));
434 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
436 else if(nPos
== aStr
.indexOf(aString_matrix
, nPos
))
438 ::basegfx::B2DHomMatrix aValue
;
441 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
444 aValue
.set(0, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 0)));
445 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
448 aValue
.set(1, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 0)));
449 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
452 aValue
.set(0, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 1)));
453 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
456 aValue
.set(1, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 1)));
457 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
460 aValue
.set(0, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 2), true));
461 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
464 aValue
.set(1, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 2), true));
465 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
467 if(!aValue
.isIdentity())
468 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj2DMatrix
>(aValue
));
470 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
480 void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix
& rFullTrans
)
482 rFullTrans
.identity();
484 const sal_uInt32 nCount
= maList
.size();
485 for(sal_uInt32
a(0); a
< nCount
; a
++)
487 ImpSdXMLExpTransObj2DBase
* pObj
= maList
[a
].get();
490 case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
:
493 // mfRotate is mathematically wrong oriented since we export/import the angle
494 // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
495 // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
496 // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
497 // to mirror the value here
498 rFullTrans
.rotate(static_cast<ImpSdXMLExpTransObj2DRotate
*>(pObj
)->mfRotate
* -1.0);
501 case IMP_SDXMLEXP_TRANSOBJ2D_SCALE
:
503 const ::basegfx::B2DTuple
& rScale
= static_cast<ImpSdXMLExpTransObj2DScale
*>(pObj
)->maScale
;
504 rFullTrans
.scale(rScale
.getX(), rScale
.getY());
507 case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
:
509 const ::basegfx::B2DTuple
& rTranslate
= static_cast<ImpSdXMLExpTransObj2DTranslate
*>(pObj
)->maTranslate
;
510 rFullTrans
.translate(rTranslate
.getX(), rTranslate
.getY());
513 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
:
515 // For to get a mathematical correct matrix from already existing documents,
516 // mirror the value here. ODF spec is unclear about direction.
517 rFullTrans
.shearX(-tan(static_cast<ImpSdXMLExpTransObj2DSkewX
*>(pObj
)->mfSkewX
));
520 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
:
522 // LibreOffice does not write skewY, OOo neither. Such files are foreign documents
523 // or manually set transformations. OOo had used the value as -tan(value) before
524 // errors were introduced, Scribus 1.5.4 uses it as -tan(value) too, MS Office does
525 // not shear at all. ODF spec is unclear about direction.
526 rFullTrans
.shearY(-tan(static_cast<ImpSdXMLExpTransObj2DSkewY
*>(pObj
)->mfSkewY
));
529 case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
:
531 rFullTrans
*= static_cast<ImpSdXMLExpTransObj2DMatrix
*>(pObj
)->maMatrix
;
536 OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
543 // base class of all 3D transform objects
545 struct ImpSdXMLExpTransObj3DBase
548 explicit ImpSdXMLExpTransObj3DBase(sal_uInt16 nType
)
552 // possible object types for 3D
554 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000
555 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001
556 #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002
557 #define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003
558 #define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004
559 #define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005
561 // classes of objects, different sizes
565 struct ImpSdXMLExpTransObj3DRotateX
: public ImpSdXMLExpTransObj3DBase
568 explicit ImpSdXMLExpTransObj3DRotateX(double fVal
)
569 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
), mfRotateX(fVal
) {}
571 struct ImpSdXMLExpTransObj3DRotateY
: public ImpSdXMLExpTransObj3DBase
574 explicit ImpSdXMLExpTransObj3DRotateY(double fVal
)
575 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
), mfRotateY(fVal
) {}
577 struct ImpSdXMLExpTransObj3DRotateZ
: public ImpSdXMLExpTransObj3DBase
580 explicit ImpSdXMLExpTransObj3DRotateZ(double fVal
)
581 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
), mfRotateZ(fVal
) {}
583 struct ImpSdXMLExpTransObj3DScale
: public ImpSdXMLExpTransObj3DBase
585 ::basegfx::B3DTuple maScale
;
586 explicit ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple
& rNew
)
587 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE
), maScale(rNew
) {}
589 struct ImpSdXMLExpTransObj3DTranslate
: public ImpSdXMLExpTransObj3DBase
591 ::basegfx::B3DTuple maTranslate
;
592 explicit ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple
& rNew
)
593 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
), maTranslate(rNew
) {}
595 struct ImpSdXMLExpTransObj3DMatrix
: public ImpSdXMLExpTransObj3DBase
597 ::basegfx::B3DHomMatrix maMatrix
;
598 explicit ImpSdXMLExpTransObj3DMatrix(::basegfx::B3DHomMatrix aNew
)
599 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
), maMatrix(std::move(aNew
)) {}
606 void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix
& rNew
)
608 if(!rNew
.isIdentity())
609 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DMatrix
>(rNew
));
612 void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix
& xHomMat
)
614 AddMatrix(basegfx::utils::UnoHomogenMatrixToB3DHomMatrix(xHomMat
));
617 // gen string for export
618 const OUString
& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter
& rConv
)
620 OUStringBuffer aNewString
;
621 OUString
aClosingBrace(")");
622 OUString
aEmptySpace(" ");
624 const sal_uInt32 nCount
= maList
.size();
625 for(sal_uInt32
a(0); a
< nCount
; a
++)
627 ImpSdXMLExpTransObj3DBase
* pObj
= maList
[a
].get();
630 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
:
632 aNewString
.append("rotatex (");
633 Imp_PutDoubleChar(aNewString
, rConv
, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateX
*>(pObj
)->mfRotateX
) );
634 aNewString
.append(aClosingBrace
);
637 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
:
639 aNewString
.append("rotatey (");
640 Imp_PutDoubleChar(aNewString
, rConv
, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateY
*>(pObj
)->mfRotateY
) );
641 aNewString
.append(aClosingBrace
);
644 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
:
646 aNewString
.append("rotatez (");
647 Imp_PutDoubleChar(aNewString
, rConv
, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateZ
*>(pObj
)->mfRotateZ
) );
648 aNewString
.append(aClosingBrace
);
651 case IMP_SDXMLEXP_TRANSOBJ3D_SCALE
:
653 aNewString
.append("scale (");
654 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DScale
*>(pObj
)->maScale
.getX());
655 aNewString
.append(aEmptySpace
);
656 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DScale
*>(pObj
)->maScale
.getY());
657 aNewString
.append(aEmptySpace
);
658 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DScale
*>(pObj
)->maScale
.getZ());
659 aNewString
.append(aClosingBrace
);
662 case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
:
664 aNewString
.append("translate (");
665 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DTranslate
*>(pObj
)->maTranslate
.getX(), true);
666 aNewString
.append(aEmptySpace
);
667 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DTranslate
*>(pObj
)->maTranslate
.getY(), true);
668 aNewString
.append(aEmptySpace
);
669 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DTranslate
*>(pObj
)->maTranslate
.getZ(), true);
670 aNewString
.append(aClosingBrace
);
673 case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
:
675 aNewString
.append("matrix (");
678 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(0, 0));
679 aNewString
.append(aEmptySpace
);
682 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(1, 0));
683 aNewString
.append(aEmptySpace
);
686 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(2, 0));
687 aNewString
.append(aEmptySpace
);
690 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(0, 1));
691 aNewString
.append(aEmptySpace
);
694 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(1, 1));
695 aNewString
.append(aEmptySpace
);
698 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(2, 1));
699 aNewString
.append(aEmptySpace
);
702 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(0, 2));
703 aNewString
.append(aEmptySpace
);
706 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(1, 2));
707 aNewString
.append(aEmptySpace
);
710 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(2, 2));
711 aNewString
.append(aEmptySpace
);
714 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(0, 3), true);
715 aNewString
.append(aEmptySpace
);
718 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(1, 3), true);
719 aNewString
.append(aEmptySpace
);
722 Imp_PutDoubleChar(aNewString
, rConv
, static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
.get(2, 3), true);
724 aNewString
.append(aClosingBrace
);
729 OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
734 // if not the last entry, add one space to next tag
735 if(a
+ 1 != maList
.size())
737 aNewString
.append(aEmptySpace
);
741 // fill string form OUString
742 msString
= aNewString
.makeStringAndClear();
747 // for Import: constructor with string, parses it and generates entries
748 SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
750 SetString(rNew
, rConv
);
753 // sets new string, parses it and generates entries
754 void SdXMLImExTransform3D::SetString(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
759 if(msString
.isEmpty())
762 const OUString aStr
= msString
;
763 const sal_Int32
nLen(aStr
.getLength());
765 static constexpr OUStringLiteral
aString_rotatex( u
"rotatex" );
766 static constexpr OUStringLiteral
aString_rotatey( u
"rotatey" );
767 static constexpr OUStringLiteral
aString_rotatez( u
"rotatez" );
768 static constexpr OUStringLiteral
aString_scale( u
"scale" );
769 static constexpr OUStringLiteral
aString_translate( u
"translate" );
770 static constexpr OUStringLiteral
aString_matrix( u
"matrix" );
777 Imp_SkipSpaces(aStr
, nPos
, nLen
);
782 if(nPos
== aStr
.indexOf(aString_rotatex
, nPos
))
787 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
788 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
790 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DRotateX
>(basegfx::deg2rad(fValue
)));
792 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
794 else if(nPos
== aStr
.indexOf(aString_rotatey
, nPos
))
799 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
800 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
802 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DRotateY
>(basegfx::deg2rad(fValue
)));
804 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
806 else if(nPos
== aStr
.indexOf(aString_rotatez
, nPos
))
811 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
812 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
814 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DRotateZ
>(basegfx::deg2rad(fValue
)));
816 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
818 else if(nPos
== aStr
.indexOf(aString_scale
, nPos
))
820 ::basegfx::B3DTuple
aValue(1.0, 1.0, 1.0);
823 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
824 aValue
.setX(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getX()));
825 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
826 aValue
.setY(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getY()));
827 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
828 aValue
.setZ(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getZ()));
830 if(1.0 != aValue
.getX() || 1.0 != aValue
.getY() || 1.0 != aValue
.getZ())
831 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DScale
>(aValue
));
833 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
835 else if(nPos
== aStr
.indexOf(aString_translate
, nPos
))
837 ::basegfx::B3DTuple aValue
;
840 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
841 aValue
.setX(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getX(), true));
842 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
843 aValue
.setY(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getY(), true));
844 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
845 aValue
.setZ(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.getZ(), true));
847 if(!aValue
.equalZero())
848 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DTranslate
>(aValue
));
850 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
852 else if(nPos
== aStr
.indexOf(aString_matrix
, nPos
))
854 ::basegfx::B3DHomMatrix aValue
;
857 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
860 aValue
.set(0, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 0)));
861 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
864 aValue
.set(1, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 0)));
865 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
868 aValue
.set(2, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 0)));
869 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
872 aValue
.set(0, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 1)));
873 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
876 aValue
.set(1, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 1)));
877 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
880 aValue
.set(2, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 1)));
881 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
884 aValue
.set(0, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 2)));
885 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
888 aValue
.set(1, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 2)));
889 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
892 aValue
.set(2, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 2)));
893 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
896 aValue
.set(0, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 3), true));
897 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
900 aValue
.set(1, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 3), true));
901 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
904 aValue
.set(2, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 3), true));
905 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
907 if(!aValue
.isIdentity())
908 maList
.push_back(std::make_shared
<ImpSdXMLExpTransObj3DMatrix
>(aValue
));
910 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
920 bool SdXMLImExTransform3D::GetFullHomogenTransform(css::drawing::HomogenMatrix
& xHomMat
)
922 ::basegfx::B3DHomMatrix aFullTransform
;
923 GetFullTransform(aFullTransform
);
925 if(!aFullTransform
.isIdentity())
927 basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aFullTransform
, xHomMat
);
934 void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix
& rFullTrans
)
936 rFullTrans
.identity();
938 const sal_uInt32 nCount
= maList
.size();
939 for(sal_uInt32
a(0); a
< nCount
; a
++)
941 ImpSdXMLExpTransObj3DBase
* pObj
= maList
[a
].get();
944 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
:
946 rFullTrans
.rotate(static_cast<ImpSdXMLExpTransObj3DRotateX
*>(pObj
)->mfRotateX
, 0.0, 0.0);
949 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
:
951 rFullTrans
.rotate(0.0, static_cast<ImpSdXMLExpTransObj3DRotateY
*>(pObj
)->mfRotateY
, 0.0);
954 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
:
956 rFullTrans
.rotate(0.0, 0.0, static_cast<ImpSdXMLExpTransObj3DRotateZ
*>(pObj
)->mfRotateZ
);
959 case IMP_SDXMLEXP_TRANSOBJ3D_SCALE
:
961 const ::basegfx::B3DTuple
& rScale
= static_cast<ImpSdXMLExpTransObj3DScale
*>(pObj
)->maScale
;
962 rFullTrans
.scale(rScale
.getX(), rScale
.getY(), rScale
.getZ());
965 case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
:
967 const ::basegfx::B3DTuple
& rTranslate
= static_cast<ImpSdXMLExpTransObj3DTranslate
*>(pObj
)->maTranslate
;
968 rFullTrans
.translate(rTranslate
.getX(), rTranslate
.getY(), rTranslate
.getZ());
971 case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
:
973 rFullTrans
*= static_cast<ImpSdXMLExpTransObj3DMatrix
*>(pObj
)->maMatrix
;
978 OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
985 SdXMLImExViewBox::SdXMLImExViewBox(double fX
, double fY
, double fW
, double fH
)
993 // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
994 SdXMLImExViewBox::SdXMLImExViewBox(OUString aNew
, const SvXMLUnitConverter
& rConv
)
995 : msString(std::move(aNew
)),
1001 if(msString
.isEmpty())
1004 const OUString aStr
= msString
;
1005 const sal_Int32
nLen(aStr
.getLength());
1008 // skip starting spaces
1009 Imp_SkipSpaces(aStr
, nPos
, nLen
);
1011 // get mX, #100617# be prepared for doubles
1012 mfX
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, mfX
);
1014 // skip spaces and commas
1015 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1017 // get mY, #100617# be prepared for doubles
1018 mfY
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, mfY
);
1020 // skip spaces and commas
1021 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1023 // get mW, #100617# be prepared for doubles
1024 mfW
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, mfW
);
1026 // skip spaces and commas
1027 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1029 // get mH, #100617# be prepared for doubles
1030 mfH
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, mfH
);
1034 const OUString
& SdXMLImExViewBox::GetExportString()
1036 OUString aNewString
;
1037 OUString
aEmptySpace(" ");
1039 Imp_PutDoubleChar(aNewString
, mfX
);
1040 aNewString
+= aEmptySpace
;
1042 Imp_PutDoubleChar(aNewString
, mfY
);
1043 aNewString
+= aEmptySpace
;
1045 Imp_PutDoubleChar(aNewString
, mfW
);
1046 aNewString
+= aEmptySpace
;
1048 Imp_PutDoubleChar(aNewString
, mfH
);
1051 msString
= aNewString
;
1056 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */