1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xexptran.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include "xexptran.hxx"
34 #include <tools/debug.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <xmloff/xmluconv.hxx>
37 #include <vcl/salbtype.hxx>
38 #include <basegfx/vector/b2dvector.hxx>
39 #include <basegfx/matrix/b2dhommatrix.hxx>
40 #include <basegfx/tuple/b3dtuple.hxx>
41 #include <basegfx/matrix/b3dhommatrix.hxx>
42 #include <tools/string.hxx>
44 using ::rtl::OUString
;
45 using ::rtl::OUStringBuffer
;
47 using namespace ::com::sun::star
;
49 //////////////////////////////////////////////////////////////////////////////
52 #define BORDER_INTEGERS_ARE_EQUAL (4)
54 //////////////////////////////////////////////////////////////////////////////
57 void Imp_SkipDouble(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
);
58 void Imp_CalcVectorValues(::basegfx::B2DVector
& aVec1
, ::basegfx::B2DVector
& aVec2
, bool& bSameLength
, bool& bSameDirection
);
60 //////////////////////////////////////////////////////////////////////////////
61 //////////////////////////////////////////////////////////////////////////////
62 // parsing help functions for simple chars
63 void Imp_SkipSpaces(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
66 && sal_Unicode(' ') == rStr
[rPos
])
70 void Imp_SkipSpacesAndOpeningBraces(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
73 && (sal_Unicode(' ') == rStr
[rPos
] || sal_Unicode('(') == rStr
[rPos
]))
77 void Imp_SkipSpacesAndCommas(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
80 && (sal_Unicode(' ') == rStr
[rPos
] || sal_Unicode(',') == rStr
[rPos
]))
84 void Imp_SkipSpacesAndClosingBraces(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
87 && (sal_Unicode(' ') == rStr
[rPos
] || sal_Unicode(')') == rStr
[rPos
]))
91 //////////////////////////////////////////////////////////////////////////////
92 //////////////////////////////////////////////////////////////////////////////
93 // parsing help functions for integer numbers
95 bool Imp_IsOnNumberChar(const OUString
& rStr
, const sal_Int32 nPos
, bool bSignAllowed
= true)
97 sal_Unicode
aChar(rStr
[nPos
]);
99 if((sal_Unicode('0') <= aChar
&& sal_Unicode('9') >= aChar
)
100 || (bSignAllowed
&& sal_Unicode('+') == aChar
)
101 || (bSignAllowed
&& sal_Unicode('-') == aChar
)
107 bool Imp_IsOnUnitChar(const OUString
& rStr
, const sal_Int32 nPos
)
109 sal_Unicode
aChar(rStr
[nPos
]);
111 if((sal_Unicode('a') <= aChar
&& sal_Unicode('z') >= aChar
)
112 || (sal_Unicode('A') <= aChar
&& sal_Unicode('Z') >= aChar
)
113 || sal_Unicode('%') == aChar
119 void Imp_SkipNumber(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
)
121 bool bSignAllowed(true);
123 while(rPos
< nLen
&& Imp_IsOnNumberChar(rStr
, rPos
, bSignAllowed
))
125 bSignAllowed
= false;
130 void Imp_SkipNumberAndSpacesAndCommas(const OUString
& rStr
, sal_Int32
& rPos
,
131 const sal_Int32 nLen
)
133 Imp_SkipNumber(rStr
, rPos
, nLen
);
134 Imp_SkipSpacesAndCommas(rStr
, rPos
, nLen
);
137 // #100617# Allow to skip doubles, too.
138 void Imp_SkipDoubleAndSpacesAndCommas(const OUString
& rStr
, sal_Int32
& rPos
,
139 const sal_Int32 nLen
)
141 Imp_SkipDouble(rStr
, rPos
, nLen
);
142 Imp_SkipSpacesAndCommas(rStr
, rPos
, nLen
);
145 void Imp_PutNumberChar(OUString
& rStr
, sal_Int32 nValue
)
147 OUStringBuffer sStringBuffer
;
148 SvXMLUnitConverter::convertNumber(sStringBuffer
, nValue
);
149 rStr
+= OUString(sStringBuffer
.makeStringAndClear());
152 void Imp_PutNumberCharWithSpace(OUString
& rStr
, sal_Int32 nValue
)
154 const sal_Int32
aLen(rStr
.getLength());
156 if(Imp_IsOnNumberChar(rStr
, aLen
- 1, false) && nValue
>= 0)
157 rStr
+= String(sal_Unicode(' '));
158 Imp_PutNumberChar(rStr
, nValue
);
161 //////////////////////////////////////////////////////////////////////////////
162 //////////////////////////////////////////////////////////////////////////////
163 // parsing help functions for double numbers
165 void Imp_SkipDouble(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32
)
167 sal_Unicode
aChar(rStr
[rPos
]);
169 if(sal_Unicode('+') == aChar
|| sal_Unicode('-') == aChar
)
170 aChar
= rStr
[++rPos
];
172 while((sal_Unicode('0') <= aChar
&& sal_Unicode('9') >= aChar
)
173 || sal_Unicode('.') == aChar
)
175 aChar
= rStr
[++rPos
];
178 if(sal_Unicode('e') == aChar
|| sal_Unicode('E') == aChar
)
180 aChar
= rStr
[++rPos
];
182 if(sal_Unicode('+') == aChar
|| sal_Unicode('-') == aChar
)
183 aChar
= rStr
[++rPos
];
185 while(sal_Unicode('0') <= aChar
&& sal_Unicode('9') >= aChar
)
187 aChar
= rStr
[++rPos
];
192 double Imp_GetDoubleChar(const OUString
& rStr
, sal_Int32
& rPos
, const sal_Int32 nLen
,
193 const SvXMLUnitConverter
& rConv
, double fRetval
, bool bLookForUnits
= false)
195 sal_Unicode
aChar(rStr
[rPos
]);
196 OUStringBuffer sNumberString
;
198 if(sal_Unicode('+') == aChar
|| sal_Unicode('-') == aChar
)
200 sNumberString
.append(rStr
[rPos
]);
201 aChar
= rStr
[++rPos
];
204 while((sal_Unicode('0') <= aChar
&& sal_Unicode('9') >= aChar
)
205 || sal_Unicode('.') == aChar
)
207 sNumberString
.append(rStr
[rPos
]);
208 aChar
= rStr
[++rPos
];
211 if(sal_Unicode('e') == aChar
|| sal_Unicode('E') == aChar
)
213 sNumberString
.append(rStr
[rPos
]);
214 aChar
= rStr
[++rPos
];
216 if(sal_Unicode('+') == aChar
|| sal_Unicode('-') == aChar
)
218 sNumberString
.append(rStr
[rPos
]);
219 aChar
= rStr
[++rPos
];
222 while(sal_Unicode('0') <= aChar
&& sal_Unicode('9') >= aChar
)
224 sNumberString
.append(rStr
[rPos
]);
225 aChar
= rStr
[++rPos
];
231 Imp_SkipSpaces(rStr
, rPos
, nLen
);
232 while(rPos
< nLen
&& Imp_IsOnUnitChar(rStr
, rPos
))
233 sNumberString
.append(rStr
[rPos
++]);
236 if(sNumberString
.getLength())
239 rConv
.convertDouble(fRetval
, sNumberString
.makeStringAndClear(), true);
241 rConv
.convertDouble(fRetval
, sNumberString
.makeStringAndClear());
247 void Imp_PutDoubleChar(OUString
& rStr
, const SvXMLUnitConverter
& rConv
, double fValue
,
248 bool bConvertUnits
= false)
250 OUStringBuffer sStringBuffer
;
253 rConv
.convertDouble(sStringBuffer
, fValue
, true);
255 rConv
.convertDouble(sStringBuffer
, fValue
);
257 rStr
+= OUString(sStringBuffer
.makeStringAndClear());
260 //////////////////////////////////////////////////////////////////////////////
261 //////////////////////////////////////////////////////////////////////////////
262 // base class of all 2D transform objects
264 struct ImpSdXMLExpTransObj2DBase
267 ImpSdXMLExpTransObj2DBase(sal_uInt16 nType
)
271 //////////////////////////////////////////////////////////////////////////////
272 // possible object types for 2D
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
281 //////////////////////////////////////////////////////////////////////////////
282 // classes of objects, different sizes
284 struct ImpSdXMLExpTransObj2DRotate
: public ImpSdXMLExpTransObj2DBase
287 ImpSdXMLExpTransObj2DRotate(double fVal
)
288 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
), mfRotate(fVal
) {}
290 struct ImpSdXMLExpTransObj2DScale
: public ImpSdXMLExpTransObj2DBase
292 ::basegfx::B2DTuple maScale
;
293 ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple
& rNew
)
294 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE
), maScale(rNew
) {}
296 struct ImpSdXMLExpTransObj2DTranslate
: public ImpSdXMLExpTransObj2DBase
298 ::basegfx::B2DTuple maTranslate
;
299 ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple
& rNew
)
300 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
), maTranslate(rNew
) {}
302 struct ImpSdXMLExpTransObj2DSkewX
: public ImpSdXMLExpTransObj2DBase
305 ImpSdXMLExpTransObj2DSkewX(double fVal
)
306 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
), mfSkewX(fVal
) {}
308 struct ImpSdXMLExpTransObj2DSkewY
: public ImpSdXMLExpTransObj2DBase
311 ImpSdXMLExpTransObj2DSkewY(double fVal
)
312 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
), mfSkewY(fVal
) {}
314 struct ImpSdXMLExpTransObj2DMatrix
: public ImpSdXMLExpTransObj2DBase
316 ::basegfx::B2DHomMatrix maMatrix
;
317 ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix
& rNew
)
318 : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
), maMatrix(rNew
) {}
321 //////////////////////////////////////////////////////////////////////////////
322 //////////////////////////////////////////////////////////////////////////////
323 // delete all entries in list
325 void SdXMLImExTransform2D::EmptyList()
327 const sal_uInt32 nCount
= maList
.size();
328 for(sal_uInt32
a(0L); a
< nCount
; a
++)
330 ImpSdXMLExpTransObj2DBase
* pObj
= maList
[a
];
334 case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
:
336 delete (ImpSdXMLExpTransObj2DRotate
*)pObj
;
339 case IMP_SDXMLEXP_TRANSOBJ2D_SCALE
:
341 delete (ImpSdXMLExpTransObj2DScale
*)pObj
;
344 case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
:
346 delete (ImpSdXMLExpTransObj2DTranslate
*)pObj
;
349 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
:
351 delete (ImpSdXMLExpTransObj2DSkewX
*)pObj
;
354 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
:
356 delete (ImpSdXMLExpTransObj2DSkewY
*)pObj
;
359 case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
:
361 delete (ImpSdXMLExpTransObj2DMatrix
*)pObj
;
366 DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
375 //////////////////////////////////////////////////////////////////////////////
378 void SdXMLImExTransform2D::AddRotate(double fNew
)
381 maList
.push_back(new ImpSdXMLExpTransObj2DRotate(fNew
));
384 void SdXMLImExTransform2D::AddScale(const ::basegfx::B2DTuple
& rNew
)
386 if(1.0 != rNew
.getX() || 1.0 != rNew
.getY())
387 maList
.push_back(new ImpSdXMLExpTransObj2DScale(rNew
));
390 void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple
& rNew
)
392 if(!rNew
.equalZero())
393 maList
.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew
));
396 void SdXMLImExTransform2D::AddSkewX(double fNew
)
399 maList
.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew
));
402 void SdXMLImExTransform2D::AddSkewY(double fNew
)
405 maList
.push_back(new ImpSdXMLExpTransObj2DSkewY(fNew
));
408 void SdXMLImExTransform2D::AddMatrix(const ::basegfx::B2DHomMatrix
& rNew
)
410 if(!rNew
.isIdentity())
411 maList
.push_back(new ImpSdXMLExpTransObj2DMatrix(rNew
));
414 //////////////////////////////////////////////////////////////////////////////
415 // gen string for export
416 const OUString
& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter
& rConv
)
419 OUString
aClosingBrace(sal_Unicode(')'));
420 OUString
aEmptySpace(sal_Unicode(' '));
422 const sal_uInt32 nCount
= maList
.size();
423 for(sal_uInt32
a(0L); a
< nCount
; a
++)
425 ImpSdXMLExpTransObj2DBase
* pObj
= maList
[a
];
428 case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
:
430 aNewString
+= OUString::createFromAscii("rotate (");
431 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DRotate
*)pObj
)->mfRotate
);
432 aNewString
+= aClosingBrace
;
435 case IMP_SDXMLEXP_TRANSOBJ2D_SCALE
:
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
;
444 case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
:
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
;
453 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
:
455 aNewString
+= OUString::createFromAscii("skewX (");
456 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DSkewX
*)pObj
)->mfSkewX
);
457 aNewString
+= aClosingBrace
;
460 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
:
462 aNewString
+= OUString::createFromAscii("skewY (");
463 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DSkewY
*)pObj
)->mfSkewY
);
464 aNewString
+= aClosingBrace
;
467 case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
:
469 aNewString
+= OUString::createFromAscii("matrix (");
472 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(0, 0));
473 aNewString
+= aEmptySpace
;
476 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(1, 0));
477 aNewString
+= aEmptySpace
;
480 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(0, 1));
481 aNewString
+= aEmptySpace
;
484 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(1, 1));
485 aNewString
+= aEmptySpace
;
488 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(0, 2), true);
489 aNewString
+= aEmptySpace
;
492 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
.get(1, 2), true);
494 aNewString
+= aClosingBrace
;
499 DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
504 // if not the last entry, add one space to next tag
505 if(a
+ 1UL != maList
.size())
507 aNewString
+= aEmptySpace
;
511 // fill string form OUString
512 msString
= aNewString
;
517 //////////////////////////////////////////////////////////////////////////////
518 // for Import: constructor with string, parses it and generates entries
519 SdXMLImExTransform2D::SdXMLImExTransform2D(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
521 SetString(rNew
, rConv
);
524 //////////////////////////////////////////////////////////////////////////////
525 // sets new string, parses it and generates entries
526 void SdXMLImExTransform2D::SetString(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
531 if(msString
.getLength())
533 const OUString
aStr(msString
.getStr(), (sal_uInt16
)msString
.getLength());
534 const sal_Int32
nLen(aStr
.getLength());
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"));
548 Imp_SkipSpaces(aStr
, nPos
, nLen
);
553 if(nPos
== aStr
.indexOf(aString_rotate
, nPos
))
557 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
558 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
560 maList
.push_back(new ImpSdXMLExpTransObj2DRotate(fValue
));
562 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
564 else if(nPos
== aStr
.indexOf(aString_scale
, nPos
))
566 ::basegfx::B2DTuple
aValue(1.0, 1.0);
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()));
573 if(aValue
.getX() != 1.0 || aValue
.getY() != 1.0)
574 maList
.push_back(new ImpSdXMLExpTransObj2DScale(aValue
));
576 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
578 else if(nPos
== aStr
.indexOf(aString_translate
, nPos
))
580 ::basegfx::B2DTuple aValue
;
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));
587 if(!aValue
.equalZero())
588 maList
.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue
));
590 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
592 else if(nPos
== aStr
.indexOf(aString_skewX
, nPos
))
596 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
597 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
599 maList
.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue
));
601 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
603 else if(nPos
== aStr
.indexOf(aString_skewY
, nPos
))
607 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
608 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
610 maList
.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue
));
612 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
614 else if(nPos
== aStr
.indexOf(aString_matrix
, nPos
))
616 ::basegfx::B2DHomMatrix aValue
;
619 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
622 aValue
.set(0, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 0)));
623 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
626 aValue
.set(1, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 0)));
627 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
630 aValue
.set(0, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 1)));
631 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
634 aValue
.set(1, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 1)));
635 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
638 aValue
.set(0, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 2), true));
639 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
642 aValue
.set(1, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 2), true));
643 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
645 if(!aValue
.isIdentity())
646 maList
.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue
));
648 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
659 void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix
& rFullTrans
)
661 rFullTrans
.identity();
663 const sal_uInt32 nCount
= maList
.size();
664 for(sal_uInt32
a(0L); a
< nCount
; a
++)
666 ImpSdXMLExpTransObj2DBase
* pObj
= maList
[a
];
669 case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE
:
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);
680 case IMP_SDXMLEXP_TRANSOBJ2D_SCALE
:
682 const ::basegfx::B2DTuple
& rScale
= ((ImpSdXMLExpTransObj2DScale
*)pObj
)->maScale
;
683 rFullTrans
.scale(rScale
.getX(), rScale
.getY());
686 case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE
:
688 const ::basegfx::B2DTuple
& rTranslate
= ((ImpSdXMLExpTransObj2DTranslate
*)pObj
)->maTranslate
;
689 rFullTrans
.translate(rTranslate
.getX(), rTranslate
.getY());
692 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX
:
694 rFullTrans
.shearX(tan(((ImpSdXMLExpTransObj2DSkewX
*)pObj
)->mfSkewX
));
697 case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY
:
699 rFullTrans
.shearY(tan(((ImpSdXMLExpTransObj2DSkewY
*)pObj
)->mfSkewY
));
702 case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX
:
704 rFullTrans
*= ((ImpSdXMLExpTransObj2DMatrix
*)pObj
)->maMatrix
;
709 DBG_ERROR("SdXMLImExTransform2D: impossible entry!");
716 //////////////////////////////////////////////////////////////////////////////
717 //////////////////////////////////////////////////////////////////////////////
718 // base class of all 3D transform objects
720 struct ImpSdXMLExpTransObj3DBase
723 ImpSdXMLExpTransObj3DBase(sal_uInt16 nType
)
727 //////////////////////////////////////////////////////////////////////////////
728 // possible object types for 3D
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
737 //////////////////////////////////////////////////////////////////////////////
738 // classes of objects, different sizes
740 struct ImpSdXMLExpTransObj3DRotateX
: public ImpSdXMLExpTransObj3DBase
743 ImpSdXMLExpTransObj3DRotateX(double fVal
)
744 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
), mfRotateX(fVal
) {}
746 struct ImpSdXMLExpTransObj3DRotateY
: public ImpSdXMLExpTransObj3DBase
749 ImpSdXMLExpTransObj3DRotateY(double fVal
)
750 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
), mfRotateY(fVal
) {}
752 struct ImpSdXMLExpTransObj3DRotateZ
: public ImpSdXMLExpTransObj3DBase
755 ImpSdXMLExpTransObj3DRotateZ(double fVal
)
756 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
), mfRotateZ(fVal
) {}
758 struct ImpSdXMLExpTransObj3DScale
: public ImpSdXMLExpTransObj3DBase
760 ::basegfx::B3DTuple maScale
;
761 ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple
& rNew
)
762 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE
), maScale(rNew
) {}
764 struct ImpSdXMLExpTransObj3DTranslate
: public ImpSdXMLExpTransObj3DBase
766 ::basegfx::B3DTuple maTranslate
;
767 ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple
& rNew
)
768 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
), maTranslate(rNew
) {}
770 struct ImpSdXMLExpTransObj3DMatrix
: public ImpSdXMLExpTransObj3DBase
772 ::basegfx::B3DHomMatrix maMatrix
;
773 ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix
& rNew
)
774 : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
), maMatrix(rNew
) {}
777 //////////////////////////////////////////////////////////////////////////////
778 //////////////////////////////////////////////////////////////////////////////
779 // delete all entries in list
781 void SdXMLImExTransform3D::EmptyList()
783 const sal_uInt32 nCount
= maList
.size();
784 for(sal_uInt32
a(0L); a
< nCount
; a
++)
786 ImpSdXMLExpTransObj3DBase
* pObj
= maList
[a
];
790 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
:
792 delete (ImpSdXMLExpTransObj3DRotateX
*)pObj
;
795 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
:
797 delete (ImpSdXMLExpTransObj3DRotateY
*)pObj
;
800 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
:
802 delete (ImpSdXMLExpTransObj3DRotateZ
*)pObj
;
805 case IMP_SDXMLEXP_TRANSOBJ3D_SCALE
:
807 delete (ImpSdXMLExpTransObj3DScale
*)pObj
;
810 case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
:
812 delete (ImpSdXMLExpTransObj3DTranslate
*)pObj
;
815 case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
:
817 delete (ImpSdXMLExpTransObj3DMatrix
*)pObj
;
822 DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
831 //////////////////////////////////////////////////////////////////////////////
834 void SdXMLImExTransform3D::AddRotateX(double fNew
)
837 maList
.push_back(new ImpSdXMLExpTransObj3DRotateX(fNew
));
840 void SdXMLImExTransform3D::AddRotateY(double fNew
)
843 maList
.push_back(new ImpSdXMLExpTransObj3DRotateY(fNew
));
846 void SdXMLImExTransform3D::AddRotateZ(double fNew
)
849 maList
.push_back(new ImpSdXMLExpTransObj3DRotateZ(fNew
));
852 void SdXMLImExTransform3D::AddScale(const ::basegfx::B3DTuple
& rNew
)
854 if(1.0 != rNew
.getX() || 1.0 != rNew
.getY() || 1.0 != rNew
.getZ())
855 maList
.push_back(new ImpSdXMLExpTransObj3DScale(rNew
));
858 void SdXMLImExTransform3D::AddTranslate(const ::basegfx::B3DTuple
& rNew
)
860 if(!rNew
.equalZero())
861 maList
.push_back(new ImpSdXMLExpTransObj3DTranslate(rNew
));
864 void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix
& rNew
)
866 if(!rNew
.isIdentity())
867 maList
.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew
));
870 void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix
& xHomMat
)
872 ::basegfx::B3DHomMatrix aExportMatrix
;
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
);
887 AddMatrix(aExportMatrix
);
890 //////////////////////////////////////////////////////////////////////////////
891 // gen string for export
892 const OUString
& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter
& rConv
)
895 OUString
aClosingBrace(sal_Unicode(')'));
896 OUString
aEmptySpace(sal_Unicode(' '));
898 const sal_uInt32 nCount
= maList
.size();
899 for(sal_uInt32
a(0L); a
< nCount
; a
++)
901 ImpSdXMLExpTransObj3DBase
* pObj
= maList
[a
];
904 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
:
906 aNewString
+= OUString::createFromAscii("rotatex (");
907 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DRotateX
*)pObj
)->mfRotateX
);
908 aNewString
+= aClosingBrace
;
911 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
:
913 aNewString
+= OUString::createFromAscii("rotatey (");
914 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DRotateY
*)pObj
)->mfRotateY
);
915 aNewString
+= aClosingBrace
;
918 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
:
920 aNewString
+= OUString::createFromAscii("rotatez (");
921 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DRotateZ
*)pObj
)->mfRotateZ
);
922 aNewString
+= aClosingBrace
;
925 case IMP_SDXMLEXP_TRANSOBJ3D_SCALE
:
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
;
936 case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
:
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
;
947 case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
:
949 aNewString
+= OUString::createFromAscii("matrix (");
952 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(0, 0));
953 aNewString
+= aEmptySpace
;
956 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(1, 0));
957 aNewString
+= aEmptySpace
;
960 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(2, 0));
961 aNewString
+= aEmptySpace
;
964 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(0, 1));
965 aNewString
+= aEmptySpace
;
968 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(1, 1));
969 aNewString
+= aEmptySpace
;
972 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(2, 1));
973 aNewString
+= aEmptySpace
;
976 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(0, 2));
977 aNewString
+= aEmptySpace
;
980 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(1, 2));
981 aNewString
+= aEmptySpace
;
984 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(2, 2));
985 aNewString
+= aEmptySpace
;
988 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(0, 3), true);
989 aNewString
+= aEmptySpace
;
992 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(1, 3), true);
993 aNewString
+= aEmptySpace
;
996 Imp_PutDoubleChar(aNewString
, rConv
, ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
.get(2, 3), true);
998 aNewString
+= aClosingBrace
;
1003 DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
1008 // if not the last entry, add one space to next tag
1009 if(a
+ 1UL != maList
.size())
1011 aNewString
+= aEmptySpace
;
1015 // fill string form OUString
1016 msString
= aNewString
;
1021 //////////////////////////////////////////////////////////////////////////////
1022 // for Import: constructor with string, parses it and generates entries
1023 SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
1025 SetString(rNew
, rConv
);
1028 //////////////////////////////////////////////////////////////////////////////
1029 // sets new string, parses it and generates entries
1030 void SdXMLImExTransform3D::SetString(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
1035 if(msString
.getLength())
1037 const OUString
aStr(msString
.getStr(), (sal_uInt16
)msString
.getLength());
1038 const sal_Int32
nLen(aStr
.getLength());
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"));
1052 Imp_SkipSpaces(aStr
, nPos
, nLen
);
1057 if(nPos
== aStr
.indexOf(aString_rotatex
, nPos
))
1062 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
1063 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
1065 maList
.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue
));
1067 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1069 else if(nPos
== aStr
.indexOf(aString_rotatey
, nPos
))
1074 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
1075 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
1077 maList
.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue
));
1079 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1081 else if(nPos
== aStr
.indexOf(aString_rotatez
, nPos
))
1086 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
1087 fValue
= Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, fValue
);
1089 maList
.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue
));
1091 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1093 else if(nPos
== aStr
.indexOf(aString_scale
, nPos
))
1095 ::basegfx::B3DTuple
aValue(1.0, 1.0, 1.0);
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()));
1105 if(1.0 != aValue
.getX() || 1.0 != aValue
.getY() || 1.0 != aValue
.getZ())
1106 maList
.push_back(new ImpSdXMLExpTransObj3DScale(aValue
));
1108 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1110 else if(nPos
== aStr
.indexOf(aString_translate
, nPos
))
1112 ::basegfx::B3DTuple aValue
;
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));
1122 if(!aValue
.equalZero())
1123 maList
.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue
));
1125 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1127 else if(nPos
== aStr
.indexOf(aString_matrix
, nPos
))
1129 ::basegfx::B3DHomMatrix aValue
;
1132 Imp_SkipSpacesAndOpeningBraces(aStr
, nPos
, nLen
);
1135 aValue
.set(0, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 0)));
1136 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1139 aValue
.set(1, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 0)));
1140 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1143 aValue
.set(2, 0, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 0)));
1144 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1147 aValue
.set(0, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 1)));
1148 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1151 aValue
.set(1, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 1)));
1152 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1155 aValue
.set(2, 1, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 1)));
1156 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1159 aValue
.set(0, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 2)));
1160 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1163 aValue
.set(1, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 2)));
1164 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1167 aValue
.set(2, 2, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 2)));
1168 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1171 aValue
.set(0, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(0, 3), true));
1172 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1175 aValue
.set(1, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(1, 3), true));
1176 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1179 aValue
.set(2, 3, Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, aValue
.get(2, 3), true));
1180 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1182 if(!aValue
.isIdentity())
1183 maList
.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue
));
1185 Imp_SkipSpacesAndClosingBraces(aStr
, nPos
, nLen
);
1196 bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix
& xHomMat
)
1198 ::basegfx::B3DHomMatrix aFullTransform
;
1199 GetFullTransform(aFullTransform
);
1201 if(!aFullTransform
.isIdentity())
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);
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);
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);
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);
1229 void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix
& rFullTrans
)
1231 rFullTrans
.identity();
1233 const sal_uInt32 nCount
= maList
.size();
1234 for(sal_uInt32
a(0L); a
< nCount
; a
++)
1236 ImpSdXMLExpTransObj3DBase
* pObj
= maList
[a
];
1237 switch(pObj
->mnType
)
1239 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X
:
1241 rFullTrans
.rotate(((ImpSdXMLExpTransObj3DRotateX
*)pObj
)->mfRotateX
, 0.0, 0.0);
1244 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y
:
1246 rFullTrans
.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY
*)pObj
)->mfRotateY
, 0.0);
1249 case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z
:
1251 rFullTrans
.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ
*)pObj
)->mfRotateZ
);
1254 case IMP_SDXMLEXP_TRANSOBJ3D_SCALE
:
1256 const ::basegfx::B3DTuple
& rScale
= ((ImpSdXMLExpTransObj3DScale
*)pObj
)->maScale
;
1257 rFullTrans
.scale(rScale
.getX(), rScale
.getY(), rScale
.getZ());
1260 case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE
:
1262 const ::basegfx::B3DTuple
& rTranslate
= ((ImpSdXMLExpTransObj3DTranslate
*)pObj
)->maTranslate
;
1263 rFullTrans
.translate(rTranslate
.getX(), rTranslate
.getY(), rTranslate
.getZ());
1266 case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX
:
1268 rFullTrans
*= ((ImpSdXMLExpTransObj3DMatrix
*)pObj
)->maMatrix
;
1273 DBG_ERROR("SdXMLImExTransform3D: impossible entry!");
1280 //////////////////////////////////////////////////////////////////////////////
1281 //////////////////////////////////////////////////////////////////////////////
1283 SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX
, sal_Int32 nY
, sal_Int32 nW
, sal_Int32 nH
)
1291 // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
1292 SdXMLImExViewBox::SdXMLImExViewBox(const OUString
& rNew
, const SvXMLUnitConverter
& rConv
)
1299 if(msString
.getLength())
1301 const OUString
aStr(msString
.getStr(), (sal_uInt16
)msString
.getLength());
1302 const sal_Int32
nLen(aStr
.getLength());
1305 // skip starting spaces
1306 Imp_SkipSpaces(aStr
, nPos
, nLen
);
1308 // get mX, #100617# be prepared for doubles
1309 mnX
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)mnX
));
1311 // skip spaces and commas
1312 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1314 // get mY, #100617# be prepared for doubles
1315 mnY
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)mnY
));
1317 // skip spaces and commas
1318 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1320 // get mW, #100617# be prepared for doubles
1321 mnW
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)mnW
));
1323 // skip spaces and commas
1324 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1326 // get mH, #100617# be prepared for doubles
1327 mnH
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)mnH
));
1331 const OUString
& SdXMLImExViewBox::GetExportString()
1333 OUString aNewString
;
1334 OUString
aEmptySpace(sal_Unicode(' '));
1336 Imp_PutNumberChar(aNewString
, mnX
);
1337 aNewString
+= aEmptySpace
;
1339 Imp_PutNumberChar(aNewString
, mnY
);
1340 aNewString
+= aEmptySpace
;
1342 Imp_PutNumberChar(aNewString
, mnW
);
1343 aNewString
+= aEmptySpace
;
1345 Imp_PutNumberChar(aNewString
, mnH
);
1348 msString
= aNewString
;
1353 //////////////////////////////////////////////////////////////////////////////
1354 //////////////////////////////////////////////////////////////////////////////
1356 SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence
* pPoints
,
1357 const SdXMLImExViewBox
& rViewBox
,
1358 const awt::Point
& rObjectPos
,
1359 const awt::Size
& rObjectSize
,
1364 DBG_ASSERT(pPoints
, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
1366 // add polygon to string
1367 sal_Int32
nCnt(pPoints
->getLength());
1369 // #104076# Convert to string only when at last one point included
1372 OUString aNewString
;
1373 awt::Point
* pArray
= pPoints
->getArray();
1375 // last point same? Ignore it.
1376 // #96328# ...but only when polygon is CLOSED
1377 if(bClosed
&& (pArray
->X
== (pArray
+ (nCnt
- 1))->X
) && (pArray
->Y
== (pArray
+ (nCnt
- 1))->Y
))
1380 // object size and ViewBox size different?
1381 bool bScale(rObjectSize
.Width
!= rViewBox
.GetWidth()
1382 || rObjectSize
.Height
!= rViewBox
.GetHeight());
1383 bool bTranslate(rViewBox
.GetX() != 0L || rViewBox
.GetY() != 0L);
1385 for(sal_Int32
a(0L); a
< nCnt
; a
++)
1387 // prepare coordinates
1388 sal_Int32
nX( pArray
->X
- rObjectPos
.X
);
1389 sal_Int32
nY( pArray
->Y
- rObjectPos
.Y
);
1391 if(bScale
&& rObjectSize
.Width
&& rObjectSize
.Height
)
1393 nX
= (nX
* rViewBox
.GetWidth()) / rObjectSize
.Width
;
1394 nY
= (nY
* rViewBox
.GetHeight()) / rObjectSize
.Height
;
1399 nX
+= rViewBox
.GetX();
1400 nY
+= rViewBox
.GetY();
1404 Imp_PutNumberChar(aNewString
, nX
);
1405 aNewString
+= String(sal_Unicode(','));
1407 // Y and space (not for last)
1408 Imp_PutNumberChar(aNewString
, nY
);
1410 aNewString
+= String(sal_Unicode(' '));
1417 msString
= aNewString
;
1421 // #100617# svg:polyline or svg:polygon values may be double precision.
1422 SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString
& rNew
,
1423 const SdXMLImExViewBox
& rViewBox
,
1424 const awt::Point
& rObjectPos
,
1425 const awt::Size
& rObjectSize
,
1426 const SvXMLUnitConverter
& rConv
)
1430 // convert string to polygon
1431 const OUString
aStr(msString
.getStr(), (sal_uInt16
)msString
.getLength());
1432 const sal_Int32
nLen(aStr
.getLength());
1434 sal_Int32
nNumPoints(0L);
1436 // skip starting spaces
1437 Imp_SkipSpaces(aStr
, nPos
, nLen
);
1439 // count points in first loop
1442 // skip number, #100617# be prepared for doubles
1443 Imp_SkipDouble(aStr
, nPos
, nLen
);
1445 // skip spaces and commas
1446 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1448 // skip number, #100617# be prepared for doubles
1449 Imp_SkipDouble(aStr
, nPos
, nLen
);
1451 // skip spaces and commas
1452 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1463 drawing::PointSequence
* pOuterSequence
= maPoly
.getArray();
1464 pOuterSequence
->realloc(nNumPoints
);
1465 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
1467 // object size and ViewBox size different?
1468 bool bScale(rObjectSize
.Width
!= rViewBox
.GetWidth()
1469 || rObjectSize
.Height
!= rViewBox
.GetHeight());
1470 bool bTranslate(rViewBox
.GetX() != 0L || rViewBox
.GetY() != 0L);
1472 // skip starting spaces
1473 Imp_SkipSpaces(aStr
, nPos
, nLen
);
1477 // prepare new parameter pair
1481 // get mX, #100617# be prepared for doubles
1482 nX
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)nX
));
1484 // skip spaces and commas
1485 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1487 // get mY, #100617# be prepared for doubles
1488 nY
= FRound(Imp_GetDoubleChar(aStr
, nPos
, nLen
, rConv
, (double)nY
));
1490 // skip spaces and commas
1491 Imp_SkipSpacesAndCommas(aStr
, nPos
, nLen
);
1493 // prepare parameters
1496 nX
-= rViewBox
.GetX();
1497 nY
-= rViewBox
.GetY();
1500 if(bScale
&& rViewBox
.GetWidth() && rViewBox
.GetHeight() )
1502 nX
= (nX
* rObjectSize
.Width
) / rViewBox
.GetWidth();
1503 nY
= (nY
* rObjectSize
.Height
) / rViewBox
.GetHeight();
1510 *pInnerSequence
= awt::Point( nX
, nY
);
1516 //////////////////////////////////////////////////////////////////////////////
1517 //////////////////////////////////////////////////////////////////////////////
1519 SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox
& rViewBox
)
1520 : mrViewBox( rViewBox
),
1521 mbIsClosed( false ),
1530 void Imp_GetPrevPos(awt::Point
*& pPrevPos1
,
1531 drawing::PolygonFlags
& aPrevFlag1
,
1532 const bool bClosed
, awt::Point
* pPoints
,
1533 drawing::PolygonFlags
* pFlags
, const sal_Int32 nPos
,
1534 const sal_Int32 nCnt
, const sal_Int32 nAdd
)
1538 pPrevPos1
= pPoints
+ ((nPos
+ nCnt
- nAdd
) % nCnt
);
1539 aPrevFlag1
= *(pFlags
+ ((nPos
+ nCnt
- nAdd
) % nCnt
));
1541 else if(nPos
> (nAdd
- 1))
1543 pPrevPos1
= pPoints
+ (nPos
- nAdd
);
1544 aPrevFlag1
= *(pFlags
+ (nPos
- nAdd
));
1550 void Imp_PrepareCoorExport(sal_Int32
& nX
, sal_Int32
& nY
,
1551 const awt::Point
* pPointArray
, const awt::Point
& rObjectPos
,
1552 const awt::Size
& rObjectSize
, const SdXMLImExViewBox
& mrViewBox
,
1553 const bool bScale
, const bool bTranslate
)
1555 nX
= pPointArray
->X
- rObjectPos
.X
;
1556 nY
= pPointArray
->Y
- rObjectPos
.Y
;
1558 if(bScale
&& rObjectSize
.Width
&& rObjectSize
.Height
)
1560 nX
= (nX
* mrViewBox
.GetWidth()) / rObjectSize
.Width
;
1561 nY
= (nY
* mrViewBox
.GetHeight()) / rObjectSize
.Height
;
1566 nX
+= mrViewBox
.GetX();
1567 nY
+= mrViewBox
.GetY();
1571 //#define TEST_QUADRATIC_CURVES
1572 #ifdef TEST_QUADRATIC_CURVES
1573 // To be able to test quadratic curve code: The code concerning to
1574 // bDoTestHere can be used (see below). Construct shapes which have their control
1575 // points on equal coordinates. When these are written, they can be
1576 // forced to create correct 'Q' and 'T' statements using this flag.
1577 // These may then be tested for import/exporting.
1578 static bool bDoTestHere(true);
1579 #endif // TEST_QUADRATIC_CURVES
1581 void SdXMLImExSvgDElement::AddPolygon(
1582 drawing::PointSequence
* pPoints
,
1583 drawing::FlagSequence
* pFlags
,
1584 const awt::Point
& rObjectPos
,
1585 const awt::Size
& rObjectSize
,
1586 bool bClosed
, bool bRelative
)
1588 DBG_ASSERT(pPoints
, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)");
1590 sal_Int32
nCnt(pPoints
->getLength());
1592 // #104076# Convert to string only when at last one point included
1595 // append polygon to string
1596 OUString aNewString
;
1597 sal_Unicode aLastCommand
= ' ';
1598 awt::Point
* pPointArray
= pPoints
->getArray();
1600 // are the flags used at all? If not forget about them
1603 sal_Int32
nFlagCnt(pFlags
->getLength());
1607 bool bFlagsUsed(false);
1608 drawing::PolygonFlags
* pFlagArray
= pFlags
->getArray();
1610 for(sal_Int32
a(0); !bFlagsUsed
&& a
< nFlagCnt
; a
++)
1611 if(drawing::PolygonFlags_NORMAL
!= *pFlagArray
++)
1623 // object size and ViewBox size different?
1624 bool bScale(rObjectSize
.Width
!= mrViewBox
.GetWidth()
1625 || rObjectSize
.Height
!= mrViewBox
.GetHeight());
1626 bool bTranslate(mrViewBox
.GetX() != 0L || mrViewBox
.GetY() != 0L);
1628 // #87202# rework of point reduction:
1629 // Test for Last point same -> closed, ignore last point. Take
1630 // some more circumstances in account when looking at curve segments.
1631 drawing::PolygonFlags
* pFlagArray
= (pFlags
) ? pFlags
->getArray() : 0L;
1632 if((pPointArray
->X
== (pPointArray
+ (nCnt
- 1))->X
) && (pPointArray
->Y
== (pPointArray
+ (nCnt
- 1))->Y
))
1636 // point needs to be ignored if point before it is
1637 // NO control point. Else the last point is needed
1638 // for exporting the last segment of the curve. That means
1639 // that the last and the first point will be saved double,
1640 // but SVG does not support a better solution here.
1641 if(nCnt
>= 2 && drawing::PolygonFlags_CONTROL
!= *(pFlagArray
+ (nCnt
- 2)))
1648 // no curve, ignore last point
1653 // bezier poly, handle curves
1654 bool bDidWriteStart(false);
1656 for(sal_Int32
a(0L); a
< nCnt
; a
++)
1658 if(!pFlags
|| drawing::PolygonFlags_CONTROL
!= *pFlagArray
)
1660 bool bDidWriteAsCurve(false);
1666 // real curve point, get previous to see if it's a control point
1667 awt::Point
* pPrevPos1
;
1668 drawing::PolygonFlags aPrevFlag1
;
1670 Imp_GetPrevPos(pPrevPos1
, aPrevFlag1
, bClosed
, pPoints
->getArray(),
1671 pFlags
->getArray(), a
, nCnt
, 1);
1673 if(pPrevPos1
&& drawing::PolygonFlags_CONTROL
== aPrevFlag1
)
1675 // get previous2 to see if it's a control point, too
1676 awt::Point
* pPrevPos2
;
1677 drawing::PolygonFlags aPrevFlag2
;
1679 Imp_GetPrevPos(pPrevPos2
, aPrevFlag2
, bClosed
, pPoints
->getArray(),
1680 pFlags
->getArray(), a
, nCnt
, 2);
1682 if(pPrevPos2
&& drawing::PolygonFlags_CONTROL
== aPrevFlag2
)
1684 // get previous3 to see if it's a curve point and if,
1685 // if it is fully symmetric or not
1686 awt::Point
* pPrevPos3
;
1687 drawing::PolygonFlags aPrevFlag3
;
1689 Imp_GetPrevPos(pPrevPos3
, aPrevFlag3
, bClosed
, pPoints
->getArray(),
1690 pFlags
->getArray(), a
, nCnt
, 3);
1694 // prepare coordinates
1697 Imp_PrepareCoorExport(nX
, nY
, pPointArray
, rObjectPos
, rObjectSize
,
1698 mrViewBox
, bScale
, bTranslate
);
1700 // #100617# test if this curve segment may be written as
1701 // a quadratic bezier
1702 // That's the case if both control points are in the same place
1703 // when they are prolonged to the common quadratic control point
1704 // Left: P = (3P1 - P0) / 2
1705 // Right: P = (3P2 - P3) / 2
1706 bool bIsQuadratic(false);
1707 const bool bEnableSaveQuadratic(false);
1709 sal_Int32
nPX_L(FRound((double)((3 * pPrevPos2
->X
) - pPrevPos3
->X
) / 2.0));
1710 sal_Int32
nPY_L(FRound((double)((3 * pPrevPos2
->Y
) - pPrevPos3
->Y
) / 2.0));
1711 sal_Int32
nPX_R(FRound((double)((3 * pPrevPos1
->X
) - pPointArray
->X
) / 2.0));
1712 sal_Int32
nPY_R(FRound((double)((3 * pPrevPos1
->Y
) - pPointArray
->Y
) / 2.0));
1717 nDist
+= abs(nPX_L
- nPX_R
);
1722 nDist
+= abs(nPY_L
- nPY_R
);
1725 if(nDist
<= BORDER_INTEGERS_ARE_EQUAL
)
1727 if(bEnableSaveQuadratic
)
1729 bIsQuadratic
= true;
1733 #ifdef TEST_QUADRATIC_CURVES
1736 bIsQuadratic
= false;
1738 if(pPrevPos1
->X
== pPrevPos2
->X
&& pPrevPos1
->Y
== pPrevPos2
->Y
)
1739 bIsQuadratic
= true;
1741 #endif // TEST_QUADRATIC_CURVES
1745 #ifdef TEST_QUADRATIC_CURVES
1748 bool bPrevPointIsSymmetric(false);
1750 if(drawing::PolygonFlags_SYMMETRIC
== aPrevFlag3
)
1752 // get previous4 to see if it's a control point
1753 awt::Point
* pPrevPos4
;
1754 drawing::PolygonFlags aPrevFlag4
;
1756 Imp_GetPrevPos(pPrevPos4
, aPrevFlag4
, bClosed
, pPoints
->getArray(),
1757 pFlags
->getArray(), a
, nCnt
, 4);
1759 if(drawing::PolygonFlags_CONTROL
== aPrevFlag4
)
1761 // okay, prevPos3 is symmetric (c2) and prevPos4
1762 // is existing control point, the 's' statement can be used
1763 bPrevPointIsSymmetric
= true;
1767 if(bPrevPointIsSymmetric
)
1769 // write a shorthand/smooth quadratic curveto entry (T)
1772 if(aLastCommand
!= sal_Unicode('t'))
1773 aNewString
+= OUString(sal_Unicode('t'));
1775 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1776 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1778 aLastCommand
= sal_Unicode('t');
1782 if(aLastCommand
!= sal_Unicode('T'))
1783 aNewString
+= OUString(sal_Unicode('T'));
1785 Imp_PutNumberCharWithSpace(aNewString
, nX
);
1786 Imp_PutNumberCharWithSpace(aNewString
, nY
);
1788 aLastCommand
= sal_Unicode('T');
1793 // prepare coordinates
1796 Imp_PrepareCoorExport(nX1
, nY1
, pPrevPos1
, rObjectPos
, rObjectSize
,
1797 mrViewBox
, bScale
, bTranslate
);
1799 // write a quadratic curveto entry (Q)
1802 if(aLastCommand
!= sal_Unicode('q'))
1803 aNewString
+= OUString(sal_Unicode('q'));
1805 Imp_PutNumberCharWithSpace(aNewString
, nX1
- mnLastX
);
1806 Imp_PutNumberCharWithSpace(aNewString
, nY1
- mnLastY
);
1807 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1808 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1810 aLastCommand
= sal_Unicode('q');
1814 if(aLastCommand
!= sal_Unicode('Q'))
1815 aNewString
+= OUString(sal_Unicode('Q'));
1817 Imp_PutNumberCharWithSpace(aNewString
, nX1
);
1818 Imp_PutNumberCharWithSpace(aNewString
, nY1
);
1819 Imp_PutNumberCharWithSpace(aNewString
, nX
);
1820 Imp_PutNumberCharWithSpace(aNewString
, nY
);
1822 aLastCommand
= sal_Unicode('Q');
1828 #endif // TEST_QUADRATIC_CURVES
1829 awt::Point
aNewPoint(nPX_L
, nPY_L
);
1830 bool bPrevPointIsSmooth(false);
1832 if(drawing::PolygonFlags_SMOOTH
== aPrevFlag3
)
1834 // get previous4 to see if it's a control point
1835 awt::Point
* pPrevPos4
;
1836 drawing::PolygonFlags aPrevFlag4
;
1838 Imp_GetPrevPos(pPrevPos4
, aPrevFlag4
, bClosed
, pPoints
->getArray(),
1839 pFlags
->getArray(), a
, nCnt
, 4);
1841 if(drawing::PolygonFlags_CONTROL
== aPrevFlag4
)
1843 // okay, prevPos3 is smooth (c1) and prevPos4
1844 // is existing control point. Test if it's even symmetric
1845 // and thus the 'T' statement may be used.
1846 ::basegfx::B2DVector
aVec1(pPrevPos4
->X
- pPrevPos3
->X
, pPrevPos4
->Y
- pPrevPos3
->Y
);
1847 ::basegfx::B2DVector
aVec2(aNewPoint
.X
- pPrevPos3
->X
, aNewPoint
.Y
- pPrevPos3
->Y
);
1848 bool bSameLength(false);
1849 bool bSameDirection(false);
1851 // get vector values
1852 Imp_CalcVectorValues(aVec1
, aVec2
, bSameLength
, bSameDirection
);
1854 if(bSameLength
&& bSameDirection
)
1855 bPrevPointIsSmooth
= true;
1859 if(bPrevPointIsSmooth
)
1861 // write a shorthand/smooth quadratic curveto entry (T)
1864 if(aLastCommand
!= sal_Unicode('t'))
1865 aNewString
+= String(sal_Unicode('t'));
1867 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1868 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1870 aLastCommand
= sal_Unicode('t');
1874 if(aLastCommand
!= sal_Unicode('T'))
1875 aNewString
+= String(sal_Unicode('T'));
1877 Imp_PutNumberCharWithSpace(aNewString
, nX
);
1878 Imp_PutNumberCharWithSpace(aNewString
, nY
);
1880 aLastCommand
= sal_Unicode('T');
1885 // prepare coordinates
1888 Imp_PrepareCoorExport(nX1
, nY1
, &aNewPoint
, rObjectPos
, rObjectSize
,
1889 mrViewBox
, bScale
, bTranslate
);
1891 // write a quadratic curveto entry (Q)
1894 if(aLastCommand
!= sal_Unicode('q'))
1895 aNewString
+= String(sal_Unicode('q'));
1897 Imp_PutNumberCharWithSpace(aNewString
, nX1
- mnLastX
);
1898 Imp_PutNumberCharWithSpace(aNewString
, nY1
- mnLastY
);
1899 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1900 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1902 aLastCommand
= sal_Unicode('q');
1906 if(aLastCommand
!= sal_Unicode('Q'))
1907 aNewString
+= String(sal_Unicode('Q'));
1909 Imp_PutNumberCharWithSpace(aNewString
, nX1
);
1910 Imp_PutNumberCharWithSpace(aNewString
, nY1
);
1911 Imp_PutNumberCharWithSpace(aNewString
, nX
);
1912 Imp_PutNumberCharWithSpace(aNewString
, nY
);
1914 aLastCommand
= sal_Unicode('Q');
1917 #ifdef TEST_QUADRATIC_CURVES
1919 #endif // TEST_QUADRATIC_CURVES
1923 bool bPrevPointIsSymmetric(false);
1925 if(drawing::PolygonFlags_SYMMETRIC
== aPrevFlag3
)
1927 // get previous4 to see if it's a control point
1928 awt::Point
* pPrevPos4
;
1929 drawing::PolygonFlags aPrevFlag4
;
1931 Imp_GetPrevPos(pPrevPos4
, aPrevFlag4
, bClosed
, pPoints
->getArray(),
1932 pFlags
->getArray(), a
, nCnt
, 4);
1934 if(drawing::PolygonFlags_CONTROL
== aPrevFlag4
)
1936 // okay, prevPos3 is symmetric (c2) and prevPos4
1937 // is existing control point, the 's' statement can be used
1938 bPrevPointIsSymmetric
= true;
1942 // prepare coordinates
1945 Imp_PrepareCoorExport(nX2
, nY2
, pPrevPos1
, rObjectPos
, rObjectSize
,
1946 mrViewBox
, bScale
, bTranslate
);
1948 if(bPrevPointIsSymmetric
)
1950 // write a shorthand/smooth curveto entry (S)
1953 if(aLastCommand
!= sal_Unicode('s'))
1954 aNewString
+= String(sal_Unicode('s'));
1956 Imp_PutNumberCharWithSpace(aNewString
, nX2
- mnLastX
);
1957 Imp_PutNumberCharWithSpace(aNewString
, nY2
- mnLastY
);
1958 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1959 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1961 aLastCommand
= sal_Unicode('s');
1965 if(aLastCommand
!= sal_Unicode('S'))
1966 aNewString
+= String(sal_Unicode('S'));
1968 Imp_PutNumberCharWithSpace(aNewString
, nX2
);
1969 Imp_PutNumberCharWithSpace(aNewString
, nY2
);
1970 Imp_PutNumberCharWithSpace(aNewString
, nX
);
1971 Imp_PutNumberCharWithSpace(aNewString
, nY
);
1973 aLastCommand
= sal_Unicode('S');
1978 // prepare coordinates
1981 Imp_PrepareCoorExport(nX1
, nY1
, pPrevPos2
, rObjectPos
, rObjectSize
,
1982 mrViewBox
, bScale
, bTranslate
);
1984 // write a curveto entry (C)
1987 if(aLastCommand
!= sal_Unicode('c'))
1988 aNewString
+= String(sal_Unicode('c'));
1990 Imp_PutNumberCharWithSpace(aNewString
, nX1
- mnLastX
);
1991 Imp_PutNumberCharWithSpace(aNewString
, nY1
- mnLastY
);
1992 Imp_PutNumberCharWithSpace(aNewString
, nX2
- mnLastX
);
1993 Imp_PutNumberCharWithSpace(aNewString
, nY2
- mnLastY
);
1994 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
1995 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
1997 aLastCommand
= sal_Unicode('c');
2001 if(aLastCommand
!= sal_Unicode('C'))
2002 aNewString
+= String(sal_Unicode('C'));
2004 Imp_PutNumberCharWithSpace(aNewString
, nX1
);
2005 Imp_PutNumberCharWithSpace(aNewString
, nY1
);
2006 Imp_PutNumberCharWithSpace(aNewString
, nX2
);
2007 Imp_PutNumberCharWithSpace(aNewString
, nY2
);
2008 Imp_PutNumberCharWithSpace(aNewString
, nX
);
2009 Imp_PutNumberCharWithSpace(aNewString
, nY
);
2011 aLastCommand
= sal_Unicode('C');
2016 // remember that current point IS written
2017 bDidWriteAsCurve
= true;
2019 // remember new last position
2028 if(!bDidWriteAsCurve
)
2030 // current point not yet written, prepare coordinates
2033 Imp_PrepareCoorExport(nX
, nY
, pPointArray
, rObjectPos
, rObjectSize
,
2034 mrViewBox
, bScale
, bTranslate
);
2038 // write as normal point
2043 if(aLastCommand
!= sal_Unicode('v'))
2044 aNewString
+= String(sal_Unicode('v'));
2046 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
2048 aLastCommand
= sal_Unicode('v');
2052 if(aLastCommand
!= sal_Unicode('V'))
2053 aNewString
+= String(sal_Unicode('V'));
2055 Imp_PutNumberCharWithSpace(aNewString
, nY
);
2057 aLastCommand
= sal_Unicode('V');
2060 else if(mnLastY
== nY
)
2064 if(aLastCommand
!= sal_Unicode('h'))
2065 aNewString
+= String(sal_Unicode('h'));
2067 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
2069 aLastCommand
= sal_Unicode('h');
2073 if(aLastCommand
!= sal_Unicode('H'))
2074 aNewString
+= String(sal_Unicode('H'));
2076 Imp_PutNumberCharWithSpace(aNewString
, nX
);
2078 aLastCommand
= sal_Unicode('H');
2085 if(aLastCommand
!= sal_Unicode('l'))
2086 aNewString
+= String(sal_Unicode('l'));
2088 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
2089 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
2091 aLastCommand
= sal_Unicode('l');
2095 if(aLastCommand
!= sal_Unicode('L'))
2096 aNewString
+= String(sal_Unicode('L'));
2098 Imp_PutNumberCharWithSpace(aNewString
, nX
);
2099 Imp_PutNumberCharWithSpace(aNewString
, nY
);
2101 aLastCommand
= sal_Unicode('L');
2107 // write as start point
2110 aNewString
+= String(sal_Unicode('m'));
2112 Imp_PutNumberCharWithSpace(aNewString
, nX
- mnLastX
);
2113 Imp_PutNumberCharWithSpace(aNewString
, nY
- mnLastY
);
2115 aLastCommand
= sal_Unicode('l');
2119 aNewString
+= String(sal_Unicode('M'));
2121 Imp_PutNumberCharWithSpace(aNewString
, nX
);
2122 Imp_PutNumberCharWithSpace(aNewString
, nY
);
2124 aLastCommand
= sal_Unicode('L');
2127 // remember start written
2128 bDidWriteStart
= true;
2131 // remember new last position
2142 // close path if closed poly
2146 aNewString
+= String(sal_Unicode('z'));
2148 aNewString
+= String(sal_Unicode('Z'));
2151 // append new string
2152 msString
+= aNewString
;
2156 // #100617# Linear double reader
2157 double Imp_ImportDoubleAndSpaces(
2158 double fRetval
, const OUString
& rStr
, sal_Int32
& rPos
,
2159 const sal_Int32 nLen
, const SvXMLUnitConverter
& rConv
)
2161 fRetval
= Imp_GetDoubleChar(rStr
, rPos
, nLen
, rConv
, fRetval
);
2162 Imp_SkipSpacesAndCommas(rStr
, rPos
, nLen
);
2166 // #100617# Allow to read doubles, too. This will need to be changed to
2167 // the usage of Imp_ImportDoubleAndSpaces(...). For now, this is sufficient
2168 // since the interface cannot transport doubles.
2169 sal_Int32
Imp_ImportNumberAndSpaces(
2170 sal_Int32 nRetval
, const OUString
& rStr
, sal_Int32
& rPos
,
2171 const sal_Int32 nLen
, const SvXMLUnitConverter
& rConv
)
2173 nRetval
= FRound(Imp_ImportDoubleAndSpaces(double(nRetval
), rStr
, rPos
, nLen
, rConv
));
2174 Imp_SkipSpacesAndCommas(rStr
, rPos
, nLen
);
2178 void Imp_PrepareCoorImport(sal_Int32
& nX
, sal_Int32
& nY
,
2179 const awt::Point
& rObjectPos
, const awt::Size
& rObjectSize
,
2180 const SdXMLImExViewBox
& rViewBox
, const bool bScale
, const bool bTranslate
)
2184 nX
-= rViewBox
.GetX();
2185 nY
-= rViewBox
.GetY();
2188 if(bScale
&& rViewBox
.GetWidth() && rViewBox
.GetHeight())
2190 nX
= (nX
* rObjectSize
.Width
) / rViewBox
.GetWidth();
2191 nY
= (nY
* rObjectSize
.Height
) / rViewBox
.GetHeight();
2198 void Imp_AddExportPoints(sal_Int32 nX
, sal_Int32 nY
,
2199 awt::Point
* pPoints
, drawing::PolygonFlags
* pFlags
,
2200 const sal_Int32 nInnerIndex
,
2201 drawing::PolygonFlags eFlag
)
2204 pPoints
[nInnerIndex
] = awt::Point( nX
, nY
);
2207 pFlags
[nInnerIndex
] = eFlag
;
2210 void Imp_CalcVectorValues(::basegfx::B2DVector
& aVec1
, ::basegfx::B2DVector
& aVec2
, bool& bSameLength
, bool& bSameDirection
)
2212 const sal_Int32
nLen1(FRound(aVec1
.getLength()));
2213 const sal_Int32
nLen2(FRound(aVec2
.getLength()));
2217 const sal_Int32
nLen3(FRound(aVec1
.getLength() * ((nLen1
+ nLen2
) / 2.0)));
2219 bSameLength
= (abs(nLen1
- nLen2
) <= BORDER_INTEGERS_ARE_EQUAL
);
2220 bSameDirection
= (nLen3
<= BORDER_INTEGERS_ARE_EQUAL
);
2223 void Imp_CorrectPolygonFlag(const sal_uInt32 nInnerIndex
, const awt::Point
* const pInnerSequence
,
2224 drawing::PolygonFlags
* const pInnerFlags
, const sal_Int32 nX1
, const sal_Int32 nY1
)
2228 const awt::Point aPPrev1
= pInnerSequence
[nInnerIndex
- 1];
2232 const awt::Point aPPrev2
= pInnerSequence
[nInnerIndex
- 2];
2233 const drawing::PolygonFlags aFPrev2
= pInnerFlags
[nInnerIndex
- 2];
2234 ::basegfx::B2DVector
aVec1(aPPrev2
.X
- aPPrev1
.X
, aPPrev2
.Y
- aPPrev1
.Y
);
2235 ::basegfx::B2DVector
aVec2(nX1
- aPPrev1
.X
, nY1
- aPPrev1
.Y
);
2236 bool bSameLength(false);
2237 bool bSameDirection(false);
2239 // get vector values
2240 Imp_CalcVectorValues(aVec1
, aVec2
, bSameLength
, bSameDirection
);
2242 if(drawing::PolygonFlags_CONTROL
== aFPrev2
)
2244 // point before is a control point
2249 // set to PolygonFlags_SYMMETRIC
2250 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_SYMMETRIC
;
2254 // set to PolygonFlags_SMOOTH
2255 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_SMOOTH
;
2260 // set to PolygonFlags_NORMAL
2261 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_NORMAL
;
2266 // point before is a simple curve point
2269 // set to PolygonFlags_SMOOTH
2270 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_SMOOTH
;
2274 // set to PolygonFlags_NORMAL
2275 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_NORMAL
;
2281 // no point before starpoint, set type to PolygonFlags_NORMAL
2282 pInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_NORMAL
;
2287 SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString
& rNew
,
2288 const SdXMLImExViewBox
& rViewBox
,
2289 const awt::Point
& rObjectPos
,
2290 const awt::Size
& rObjectSize
,
2291 const SvXMLUnitConverter
& rConv
)
2293 mrViewBox( rViewBox
),
2294 mbIsClosed( false ),
2301 // convert string to polygon
2302 const OUString
aStr(msString
.getStr(), msString
.getLength());
2303 const sal_Int32
nLen(aStr
.getLength());
2305 sal_Int32
nNumPolys(0L);
2306 bool bEllipticalArc(false);
2308 // object size and ViewBox size different?
2309 bool bScale(rObjectSize
.Width
!= mrViewBox
.GetWidth()
2310 || rObjectSize
.Height
!= mrViewBox
.GetHeight());
2311 bool bTranslate(mrViewBox
.GetX() != 0L || mrViewBox
.GetY() != 0L);
2313 // first loop: count polys and get flags
2314 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2318 switch(aStr
[nPos
++])
2350 // normal, interpreted values. All okay.
2356 // Not yet interpreted value.
2357 bEllipticalArc
= true;
2363 DBG_ASSERT(!bEllipticalArc
, "XMLIMP: non-interpreted tags in svg:d element!");
2368 maPoly
.realloc(nNumPolys
);
2370 maFlag
.realloc(nNumPolys
);
2372 // get outer sequences
2373 drawing::PointSequence
* pOuterSequence
= maPoly
.getArray();
2374 drawing::FlagSequence
* pOuterFlags
= (IsCurve()) ? maFlag
.getArray() : 0L;
2376 // prepare new loop, count
2377 sal_uInt32
nPointCount(0L);
2379 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2381 // #104076# reset closed flag for next to be started polygon
2392 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2394 // #104076# remember closed state of current polygon
2402 // new poly starts, end-process current poly
2405 // #104076# If this partial polygon is closed, use one more point
2406 // to represent that
2412 pOuterSequence
->realloc(nPointCount
);
2417 pOuterFlags
->realloc(nPointCount
);
2421 // reset point count for next polygon
2425 // #104076# reset closed flag for next to be started polygon
2428 // NO break, continue in next case
2434 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2436 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2438 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2439 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2450 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2452 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2454 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2463 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2465 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2467 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2468 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2469 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2470 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2479 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2481 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2483 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2484 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2485 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2486 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2487 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2488 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2494 // #100617# quadratic beziers, supported as cubic ones
2499 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2501 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2503 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2504 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2505 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2506 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2508 // use three points since quadratic is imported as cubic
2514 // #100617# relative quadratic beziers, supported as cubic ones
2519 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2521 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2523 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2524 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2526 // use three points since quadratic is imported as cubic
2532 // #100617# not yet supported: elliptical arc
2536 DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
2538 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2540 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2542 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2543 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2544 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2545 Imp_SkipNumberAndSpacesAndCommas(aStr
, nPos
, nLen
);
2546 Imp_SkipNumberAndSpacesAndCommas(aStr
, nPos
, nLen
);
2547 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2548 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
2556 DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
2562 // alloc last poly (when points used)
2565 // #104076# If this partial polygon is closed, use one more point
2566 // to represent that
2572 pOuterSequence
->realloc(nPointCount
);
2577 pOuterFlags
->realloc(nPointCount
);
2582 // set pointers back
2583 pOuterSequence
= maPoly
.getArray();
2584 pOuterFlags
= (IsCurve()) ? maFlag
.getArray() : 0L;
2585 awt::Point
* pNotSoInnerSequence
= 0L;
2586 drawing::PolygonFlags
* pNotSoInnerFlags
= 0L;
2587 sal_uInt32
nInnerIndex(0L);
2589 // prepare new loop, read points
2591 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2593 // #104076# reset closed flag for next to be started polygon
2598 bool bRelative(false);
2606 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2608 // #104076# remember closed state of current polygon
2611 // closed: add first point again
2612 // sal_Int32 nX(pInnerSequence[0].X);
2613 // sal_Int32 nY(pInnerSequence[0].Y);
2614 // Imp_AddExportPoints(nX, nY, pInnerSequence, pInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL);
2625 // #104076# end-process current poly
2628 if(pNotSoInnerSequence
)
2630 // closed: add first point again
2631 sal_Int32
nX(pNotSoInnerSequence
[0].X
);
2632 sal_Int32
nY(pNotSoInnerSequence
[0].Y
);
2633 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
2636 // reset closed flag for next to be started polygon
2641 pNotSoInnerSequence
= pOuterSequence
->getArray();
2646 pNotSoInnerFlags
= pOuterFlags
->getArray();
2653 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2655 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2657 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2658 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2666 // set last position
2670 // calc transform and add point and flag
2671 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2672 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
2684 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2686 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2688 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2689 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2697 // set last position
2701 // calc transform and add point and flag
2702 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2703 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
2715 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2717 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2719 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2720 sal_Int32
nY(mnLastY
);
2725 // set last position
2728 // calc transform and add point and flag
2729 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2730 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
2742 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2744 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2746 sal_Int32
nX(mnLastX
);
2747 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2752 // set last position
2755 // calc transform and add point and flag
2756 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2757 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
2769 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2771 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2775 sal_Int32
nX2(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2776 sal_Int32
nY2(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2777 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2778 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2788 // set last position
2792 // calc transform for new points
2793 Imp_PrepareCoorImport(nX2
, nY2
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2794 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2796 // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
2797 // and the Point X1,Y1 can be constructed by mirroring the point before it.
2802 awt::Point aPPrev1
= pNotSoInnerSequence
[nInnerIndex
- 1];
2806 awt::Point aPPrev2
= pNotSoInnerSequence
[nInnerIndex
- 2];
2807 nX1
= aPPrev1
.X
-(aPPrev2
.X
- aPPrev1
.X
);
2808 nY1
= aPPrev1
.Y
-(aPPrev2
.Y
- aPPrev1
.Y
);
2811 // set curve point to symmetric
2812 pNotSoInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_SYMMETRIC
;
2815 // add calculated control point
2816 Imp_AddExportPoints(nX1
, nY1
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2818 // add new points and set flags
2819 Imp_AddExportPoints(nX2
, nY2
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2820 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_SMOOTH
);
2832 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2834 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2836 sal_Int32
nX1(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2837 sal_Int32
nY1(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2838 sal_Int32
nX2(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2839 sal_Int32
nY2(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2840 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2841 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2853 // set last position
2857 // calc transform for new points
2858 Imp_PrepareCoorImport(nX1
, nY1
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2859 Imp_PrepareCoorImport(nX2
, nY2
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2860 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2862 // correct polygon flag for previous point
2863 Imp_CorrectPolygonFlag(nInnerIndex
, pNotSoInnerSequence
, pNotSoInnerFlags
, nX1
, nY1
);
2865 // add new points and set flags
2866 Imp_AddExportPoints(nX1
, nY1
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2867 Imp_AddExportPoints(nX2
, nY2
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2868 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_SMOOTH
);
2873 // #100617# quadratic beziers are imported as cubic
2881 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2883 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2885 sal_Int32
nXX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2886 sal_Int32
nYY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2887 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2888 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2898 // set last position
2902 // calc transform for new points
2903 Imp_PrepareCoorImport(nXX
, nYY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2904 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2907 awt::Point aPPrev1
= (nInnerIndex
) ? pNotSoInnerSequence
[nInnerIndex
-1] : pNotSoInnerSequence
[0];
2908 sal_Int32 nX1
= FRound((double)((nXX
* 2) + aPPrev1
.X
) / 3.0);
2909 sal_Int32 nY1
= FRound((double)((nYY
* 2) + aPPrev1
.Y
) / 3.0);
2910 sal_Int32 nX2
= FRound((double)((nXX
* 2) + nX
) / 3.0);
2911 sal_Int32 nY2
= FRound((double)((nYY
* 2) + nY
) / 3.0);
2913 // correct polygon flag for previous point
2914 Imp_CorrectPolygonFlag(nInnerIndex
, pNotSoInnerSequence
, pNotSoInnerFlags
, nX1
, nY1
);
2916 // add new points and set flags
2917 Imp_AddExportPoints(nX1
, nY1
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2918 Imp_AddExportPoints(nX2
, nY2
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2919 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_SMOOTH
);
2924 // #100617# relative quadratic beziers are imported as cubic
2932 Imp_SkipSpaces(aStr
, nPos
, nLen
);
2934 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
2938 sal_Int32
nX(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2939 sal_Int32
nY(Imp_ImportNumberAndSpaces(0L, aStr
, nPos
, nLen
, rConv
));
2947 // set last position
2951 // calc transform for new points
2952 Imp_PrepareCoorImport(nX
, nY
, rObjectPos
, rObjectSize
, mrViewBox
, bScale
, bTranslate
);
2954 // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC
2955 // and the Point X1,Y1 can be constructed by mirroring the point before it.
2958 awt::Point aPPrev1
= pNotSoInnerSequence
[0];
2962 aPPrev1
= pNotSoInnerSequence
[nInnerIndex
- 1];
2966 awt::Point aPPrev2
= pNotSoInnerSequence
[nInnerIndex
- 2];
2967 nXX
= aPPrev1
.X
-(aPPrev2
.X
- aPPrev1
.X
);
2968 nYY
= aPPrev1
.Y
-(aPPrev2
.Y
- aPPrev1
.Y
);
2971 // set curve point to smooth here, since length
2972 // is changed and thus only c1 can be used.
2973 pNotSoInnerFlags
[nInnerIndex
- 1] = drawing::PolygonFlags_SMOOTH
;
2977 sal_Int32 nX1
= FRound((double)((nXX
* 2) + aPPrev1
.X
) / 3.0);
2978 sal_Int32 nY1
= FRound((double)((nYY
* 2) + aPPrev1
.Y
) / 3.0);
2979 sal_Int32 nX2
= FRound((double)((nXX
* 2) + nX
) / 3.0);
2980 sal_Int32 nY2
= FRound((double)((nYY
* 2) + nY
) / 3.0);
2982 // correct polygon flag for previous point
2983 Imp_CorrectPolygonFlag(nInnerIndex
, pNotSoInnerSequence
, pNotSoInnerFlags
, nX1
, nY1
);
2985 // add new points and set flags
2986 Imp_AddExportPoints(nX1
, nY1
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2987 Imp_AddExportPoints(nX2
, nY2
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_CONTROL
);
2988 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_SMOOTH
);
2993 // #100617# not yet supported: elliptical arc
2997 DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!");
2999 Imp_SkipSpaces(aStr
, nPos
, nLen
);
3001 while(nPos
< nLen
&& Imp_IsOnNumberChar(aStr
, nPos
))
3003 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
3004 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
3005 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
3006 Imp_SkipNumberAndSpacesAndCommas(aStr
, nPos
, nLen
);
3007 Imp_SkipNumberAndSpacesAndCommas(aStr
, nPos
, nLen
);
3008 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
3009 Imp_SkipDoubleAndSpacesAndCommas(aStr
, nPos
, nLen
);
3017 DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!");
3023 // #104076# end-process closed state of last poly
3026 if(pNotSoInnerSequence
)
3028 // closed: add first point again
3029 sal_Int32
nX(pNotSoInnerSequence
[0].X
);
3030 sal_Int32
nY(pNotSoInnerSequence
[0].Y
);
3031 Imp_AddExportPoints(nX
, nY
, pNotSoInnerSequence
, pNotSoInnerFlags
, nInnerIndex
++, drawing::PolygonFlags_NORMAL
);
3035 // #87202# If it's a curve and it's closed the last point maybe too much
3036 // and just exported since SVG does not allow special handling of same
3037 // start and end point, remove this last point.
3038 // Evtl. correct the last curve flags, too.
3039 if(IsCurve() && IsClosed())
3041 // make one more loop over the PolyPolygon
3042 pOuterSequence
= maPoly
.getArray();
3043 pOuterFlags
= maFlag
.getArray();
3044 sal_Int32
nOuterCnt(maPoly
.getLength());
3046 for(sal_Int32
a(0); a
< nOuterCnt
; a
++)
3048 // get Polygon pointers
3049 awt::Point
* pInnerSequence
= pOuterSequence
->getArray();
3050 drawing::PolygonFlags
* pInnerFlags
= pOuterFlags
->getArray();
3051 sal_Int32
nInnerCnt(pOuterSequence
->getLength());
3053 while( nInnerCnt
>= 2
3054 && ((pInnerSequence
+ (nInnerCnt
- 2))->X
== (pInnerSequence
+ (nInnerCnt
- 1))->X
)
3055 && ((pInnerSequence
+ (nInnerCnt
- 2))->Y
== (pInnerSequence
+ (nInnerCnt
- 1))->Y
)
3056 && drawing::PolygonFlags_CONTROL
!= *(pInnerFlags
+ (nInnerCnt
- 2)))
3058 // remove last point from array
3059 pOuterSequence
->realloc(nInnerCnt
- 1);
3060 pOuterFlags
->realloc(nInnerCnt
- 1);
3063 pInnerSequence
= pOuterSequence
->getArray();
3064 pInnerFlags
= pOuterFlags
->getArray();
3065 nInnerCnt
= pOuterSequence
->getLength();
3068 // now evtl. correct the last curve flags
3071 if( pInnerSequence
->X
== (pInnerSequence
+ (nInnerCnt
- 1))->X
3072 && pInnerSequence
->Y
== (pInnerSequence
+ (nInnerCnt
- 1))->Y
3073 && drawing::PolygonFlags_CONTROL
== *(pInnerFlags
+ 1)
3074 && drawing::PolygonFlags_CONTROL
== *(pInnerFlags
+ (nInnerCnt
- 2)))
3076 awt::Point aPrev
= *(pInnerSequence
+ (nInnerCnt
- 2));
3077 awt::Point aCurr
= *pInnerSequence
;
3078 awt::Point aNext
= *(pInnerSequence
+ 1);
3079 ::basegfx::B2DVector
aVec1(aPrev
.X
- aCurr
.X
, aPrev
.Y
- aCurr
.Y
);
3080 ::basegfx::B2DVector
aVec2(aNext
.X
- aCurr
.X
, aNext
.Y
- aCurr
.Y
);
3081 bool bSameLength(false);
3082 bool bSameDirection(false);
3084 // get vector values
3085 Imp_CalcVectorValues(aVec1
, aVec2
, bSameLength
, bSameDirection
);
3087 // set correct flag value
3092 // set to PolygonFlags_SYMMETRIC
3093 *pInnerFlags
= drawing::PolygonFlags_SYMMETRIC
;
3094 *(pInnerFlags
+ (nInnerCnt
- 1)) = drawing::PolygonFlags_SYMMETRIC
;
3098 // set to PolygonFlags_SMOOTH
3099 *pInnerFlags
= drawing::PolygonFlags_SMOOTH
;
3100 *(pInnerFlags
+ (nInnerCnt
- 1)) = drawing::PolygonFlags_SMOOTH
;
3105 // set to PolygonFlags_NORMAL
3106 *pInnerFlags
= drawing::PolygonFlags_NORMAL
;
3107 *(pInnerFlags
+ (nInnerCnt
- 1)) = drawing::PolygonFlags_NORMAL
;
3112 // switch to next Polygon