Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "xexptran.hxx"
30 : : #include <tools/debug.hxx>
31 : : #include <rtl/ustrbuf.hxx>
32 : : #include <sax/tools/converter.hxx>
33 : : #include <xmloff/xmluconv.hxx>
34 : : #include <xmloff/xmlexp.hxx>
35 : : #include <xmloff/xmlimp.hxx>
36 : : #include <tools/helpers.hxx>
37 : : #include <basegfx/vector/b2dvector.hxx>
38 : : #include <basegfx/matrix/b2dhommatrix.hxx>
39 : : #include <basegfx/tuple/b3dtuple.hxx>
40 : : #include <basegfx/matrix/b3dhommatrix.hxx>
41 : : #include <basegfx/polygon/b2dpolypolygon.hxx>
42 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
43 : : #include <basegfx/tools/unotools.hxx>
44 : :
45 : : using ::rtl::OUString;
46 : : using ::rtl::OUStringBuffer;
47 : :
48 : : using namespace ::com::sun::star;
49 : :
50 : : //////////////////////////////////////////////////////////////////////////////
51 : : // Defines
52 : :
53 : : #define BORDER_INTEGERS_ARE_EQUAL (4)
54 : :
55 : : //////////////////////////////////////////////////////////////////////////////
56 : : // Predeclarations
57 : :
58 : : void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen);
59 : 0 : void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection)
60 : : {
61 : 0 : const sal_Int32 nLen1(FRound(aVec1.getLength()));
62 : 0 : const sal_Int32 nLen2(FRound(aVec2.getLength()));
63 : 0 : aVec1.normalize();
64 : 0 : aVec2.normalize();
65 : 0 : aVec1 += aVec2;
66 : 0 : const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0)));
67 : :
68 [ # # ][ # # ]: 0 : bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL);
69 : 0 : bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL);
70 : 0 : }
71 : :
72 : :
73 : : //////////////////////////////////////////////////////////////////////////////
74 : : //////////////////////////////////////////////////////////////////////////////
75 : : // parsing help functions for simple chars
76 : 461 : void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
77 : : {
78 [ + - - + ]: 922 : while(rPos < nLen
[ - + ]
79 : 461 : && sal_Unicode(' ') == rStr[rPos])
80 : 0 : rPos++;
81 : 461 : }
82 : :
83 : 24 : void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
84 : : {
85 [ + - + + : 192 : while(rPos < nLen
+ + ][ + + ]
86 : 120 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos]))
87 : 48 : rPos++;
88 : 24 : }
89 : :
90 : 1659 : void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
91 : : {
92 [ + + + + : 8439 : while(rPos < nLen
+ + ][ + + ]
93 : 5145 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos]))
94 : 1635 : rPos++;
95 : 1659 : }
96 : :
97 : 24 : void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
98 : : {
99 [ + + + + : 144 : while(rPos < nLen
+ + ][ + + ]
100 : 84 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos]))
101 : 36 : rPos++;
102 : 24 : }
103 : :
104 : : //////////////////////////////////////////////////////////////////////////////
105 : : //////////////////////////////////////////////////////////////////////////////
106 : : // parsing help functions for integer numbers
107 : :
108 : 60 : bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
109 : : {
110 : 60 : sal_Unicode aChar(rStr[nPos]);
111 : :
112 [ + + ][ - + ]: 60 : if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
[ # # ][ - + ]
[ # # ][ + - ]
113 : : || (bSignAllowed && sal_Unicode('+') == aChar)
114 : : || (bSignAllowed && sal_Unicode('-') == aChar)
115 : : )
116 : 36 : return true;
117 : 60 : return false;
118 : : }
119 : :
120 : 72 : bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos)
121 : : {
122 : 72 : sal_Unicode aChar(rStr[nPos]);
123 : :
124 [ - + ][ - + ]: 72 : if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
[ # # ][ - + ]
[ + + ]
125 : : || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
126 : : || sal_Unicode('%') == aChar
127 : : )
128 : 48 : return true;
129 : 72 : return false;
130 : : }
131 : :
132 : 0 : void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
133 : : {
134 : 0 : bool bSignAllowed(true);
135 : :
136 [ # # ][ # # ]: 0 : while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed))
[ # # ]
137 : : {
138 : 0 : bSignAllowed = false;
139 : 0 : rPos++;
140 : : }
141 : 0 : }
142 : :
143 : 0 : void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
144 : : const sal_Int32 nLen)
145 : : {
146 : 0 : Imp_SkipNumber(rStr, rPos, nLen);
147 : 0 : Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
148 : 0 : }
149 : :
150 : 108 : void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue)
151 : : {
152 : 108 : OUStringBuffer sStringBuffer;
153 [ + - ]: 108 : ::sax::Converter::convertNumber(sStringBuffer, nValue);
154 [ + - ]: 108 : rStr += OUString(sStringBuffer.makeStringAndClear());
155 : 108 : }
156 : :
157 : 60 : void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue)
158 : : {
159 : 60 : const sal_Int32 aLen(rStr.getLength());
160 [ + - ]: 60 : if(aLen)
161 [ + + ][ + + ]: 60 : if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0)
[ + + ]
162 : 24 : rStr += rtl::OUString(static_cast<sal_Unicode>(' '));
163 : 60 : Imp_PutNumberChar(rStr, nValue);
164 : 60 : }
165 : :
166 : : //////////////////////////////////////////////////////////////////////////////
167 : : //////////////////////////////////////////////////////////////////////////////
168 : : // parsing help functions for double numbers
169 : :
170 : 240 : void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32)
171 : : {
172 : 240 : sal_Unicode aChar(rStr[rPos]);
173 : :
174 [ - + ][ + - ]: 240 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
175 : 0 : aChar = rStr[++rPos];
176 : :
177 [ + + ][ - + ]: 1071 : while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
[ - + ][ + + ]
178 : : || sal_Unicode('.') == aChar)
179 : : {
180 : 831 : aChar = rStr[++rPos];
181 : : }
182 : :
183 [ + - ][ - + ]: 240 : if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
184 : : {
185 : 0 : aChar = rStr[++rPos];
186 : :
187 [ # # ][ # # ]: 0 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
188 : 0 : aChar = rStr[++rPos];
189 : :
190 [ # # ][ # # ]: 0 : while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
[ # # ]
191 : : {
192 : 0 : aChar = rStr[++rPos];
193 : : }
194 : : }
195 : 240 : }
196 : :
197 : 1832 : double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen,
198 : : const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
199 : : {
200 : 1832 : sal_Unicode aChar(rStr[rPos]);
201 : 1832 : OUStringBuffer sNumberString;
202 : :
203 [ + + ][ + - ]: 1832 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
204 : : {
205 [ + - ]: 3 : sNumberString.append(rStr[rPos]);
206 : 3 : aChar = rStr[++rPos];
207 : : }
208 : :
209 [ + + ][ + + ]: 7161 : while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
[ + + ][ + + ]
210 : : || sal_Unicode('.') == aChar)
211 : : {
212 [ + - ]: 5329 : sNumberString.append(rStr[rPos]);
213 : 5329 : aChar = rStr[++rPos];
214 : : }
215 : :
216 [ + - ][ - + ]: 1832 : if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
217 : : {
218 [ # # ]: 0 : sNumberString.append(rStr[rPos]);
219 : 0 : aChar = rStr[++rPos];
220 : :
221 [ # # ][ # # ]: 0 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
222 : : {
223 [ # # ]: 0 : sNumberString.append(rStr[rPos]);
224 : 0 : aChar = rStr[++rPos];
225 : : }
226 : :
227 [ # # ][ # # ]: 0 : while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
[ # # ]
228 : : {
229 [ # # ]: 0 : sNumberString.append(rStr[rPos]);
230 : 0 : aChar = rStr[++rPos];
231 : : }
232 : : }
233 : :
234 [ + + ]: 1832 : if(bLookForUnits)
235 : : {
236 : 24 : Imp_SkipSpaces(rStr, rPos, nLen);
237 [ + - ][ + + ]: 72 : while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
[ + + ]
238 [ + - ]: 48 : sNumberString.append(rStr[rPos++]);
239 : : }
240 : :
241 [ + - ]: 1832 : if(sNumberString.getLength())
242 : : {
243 [ + + ]: 1832 : if(bLookForUnits)
244 [ + - ][ + - ]: 24 : rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true);
245 : : else
246 : : {
247 : : ::sax::Converter::convertDouble(fRetval,
248 [ + - ][ + - ]: 1808 : sNumberString.makeStringAndClear());
249 : : }
250 : : }
251 : :
252 : 1832 : return fRetval;
253 : : }
254 : :
255 : 0 : void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
256 : : bool bConvertUnits = false)
257 : : {
258 : 0 : OUStringBuffer sStringBuffer;
259 : :
260 [ # # ]: 0 : if(bConvertUnits)
261 [ # # ]: 0 : rConv.convertDouble(sStringBuffer, fValue, true);
262 : : else
263 : : {
264 [ # # ]: 0 : ::sax::Converter::convertDouble(sStringBuffer, fValue);
265 : : }
266 : :
267 [ # # ]: 0 : rStr += OUString(sStringBuffer.makeStringAndClear());
268 : 0 : }
269 : :
270 : : //////////////////////////////////////////////////////////////////////////////
271 : : //////////////////////////////////////////////////////////////////////////////
272 : : // base class of all 2D transform objects
273 : :
274 : : struct ImpSdXMLExpTransObj2DBase
275 : : {
276 : : sal_uInt16 mnType;
277 : 24 : ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
278 : 24 : : mnType(nType) {}
279 : : };
280 : :
281 : : //////////////////////////////////////////////////////////////////////////////
282 : : // possible object types for 2D
283 : :
284 : : #define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000
285 : : #define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001
286 : : #define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002
287 : : #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003
288 : : #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004
289 : : #define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005
290 : :
291 : : //////////////////////////////////////////////////////////////////////////////
292 : : // classes of objects, different sizes
293 : :
294 : : struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
295 : : {
296 : : double mfRotate;
297 : 12 : ImpSdXMLExpTransObj2DRotate(double fVal)
298 : 12 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {}
299 : : };
300 : 0 : struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
301 : : {
302 : : ::basegfx::B2DTuple maScale;
303 : 0 : ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
304 : 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {}
305 : : };
306 : 12 : struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
307 : : {
308 : : ::basegfx::B2DTuple maTranslate;
309 : 12 : ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
310 : 12 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {}
311 : : };
312 : : struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
313 : : {
314 : : double mfSkewX;
315 : 0 : ImpSdXMLExpTransObj2DSkewX(double fVal)
316 : 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {}
317 : : };
318 : : struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
319 : : {
320 : : double mfSkewY;
321 : 0 : ImpSdXMLExpTransObj2DSkewY(double fVal)
322 : 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {}
323 : : };
324 : 0 : struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
325 : : {
326 : : ::basegfx::B2DHomMatrix maMatrix;
327 : 0 : ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
328 : 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {}
329 : : };
330 : :
331 : : //////////////////////////////////////////////////////////////////////////////
332 : : //////////////////////////////////////////////////////////////////////////////
333 : : // delete all entries in list
334 : :
335 : 644 : void SdXMLImExTransform2D::EmptyList()
336 : : {
337 : 644 : const sal_uInt32 nCount = maList.size();
338 [ + + ]: 668 : for(sal_uInt32 a(0L); a < nCount; a++)
339 : : {
340 : 24 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
341 : :
342 [ + - + - : 24 : switch(pObj->mnType)
- - - ]
343 : : {
344 : : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
345 : : {
346 : 12 : delete (ImpSdXMLExpTransObj2DRotate*)pObj;
347 : 12 : break;
348 : : }
349 : : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
350 : : {
351 [ # # ]: 0 : delete (ImpSdXMLExpTransObj2DScale*)pObj;
352 : 0 : break;
353 : : }
354 : : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
355 : : {
356 [ + - ]: 12 : delete (ImpSdXMLExpTransObj2DTranslate*)pObj;
357 : 12 : break;
358 : : }
359 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
360 : : {
361 : 0 : delete (ImpSdXMLExpTransObj2DSkewX*)pObj;
362 : 0 : break;
363 : : }
364 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
365 : : {
366 : 0 : delete (ImpSdXMLExpTransObj2DSkewY*)pObj;
367 : 0 : break;
368 : : }
369 : : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
370 : : {
371 [ # # ]: 0 : delete (ImpSdXMLExpTransObj2DMatrix*)pObj;
372 : 0 : break;
373 : : }
374 : : default :
375 : : {
376 : : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
377 : 0 : break;
378 : : }
379 : : }
380 : : }
381 : :
382 : 644 : maList.clear();
383 : 644 : }
384 : :
385 : : //////////////////////////////////////////////////////////////////////////////
386 : : // add members
387 : :
388 : 0 : void SdXMLImExTransform2D::AddRotate(double fNew)
389 : : {
390 [ # # ]: 0 : if(fNew != 0.0)
391 [ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew));
392 : 0 : }
393 : :
394 : 0 : void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
395 : : {
396 [ # # ]: 0 : if(!rNew.equalZero())
397 [ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew));
398 : 0 : }
399 : :
400 : 0 : void SdXMLImExTransform2D::AddSkewX(double fNew)
401 : : {
402 [ # # ]: 0 : if(fNew != 0.0)
403 [ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew));
404 : 0 : }
405 : :
406 : : //////////////////////////////////////////////////////////////////////////////
407 : : // gen string for export
408 : 0 : const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv)
409 : : {
410 : 0 : OUString aNewString;
411 : 0 : OUString aClosingBrace(sal_Unicode(')'));
412 : 0 : OUString aEmptySpace(sal_Unicode(' '));
413 : :
414 : 0 : const sal_uInt32 nCount = maList.size();
415 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nCount; a++)
416 : : {
417 : 0 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
418 [ # # # # : 0 : switch(pObj->mnType)
# # # ]
419 : : {
420 : : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
421 : : {
422 : 0 : aNewString += OUString( "rotate (" );
423 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate);
424 : 0 : aNewString += aClosingBrace;
425 : 0 : break;
426 : : }
427 : : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
428 : : {
429 : 0 : aNewString += OUString( "scale (" );
430 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX());
431 : 0 : aNewString += aEmptySpace;
432 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY());
433 : 0 : aNewString += aClosingBrace;
434 : 0 : break;
435 : : }
436 : : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
437 : : {
438 : 0 : aNewString += OUString( "translate (" );
439 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true);
440 : 0 : aNewString += aEmptySpace;
441 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true);
442 : 0 : aNewString += aClosingBrace;
443 : 0 : break;
444 : : }
445 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
446 : : {
447 : 0 : aNewString += OUString( "skewX (" );
448 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX);
449 : 0 : aNewString += aClosingBrace;
450 : 0 : break;
451 : : }
452 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
453 : : {
454 : 0 : aNewString += OUString( "skewY (" );
455 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY);
456 : 0 : aNewString += aClosingBrace;
457 : 0 : break;
458 : : }
459 : : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
460 : : {
461 : 0 : aNewString += OUString( "matrix (" );
462 : :
463 : : // a
464 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0));
465 : 0 : aNewString += aEmptySpace;
466 : :
467 : : // b
468 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0));
469 : 0 : aNewString += aEmptySpace;
470 : :
471 : : // c
472 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1));
473 : 0 : aNewString += aEmptySpace;
474 : :
475 : : // d
476 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1));
477 : 0 : aNewString += aEmptySpace;
478 : :
479 : : // e
480 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true);
481 : 0 : aNewString += aEmptySpace;
482 : :
483 : : // f
484 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true);
485 : :
486 : 0 : aNewString += aClosingBrace;
487 : 0 : break;
488 : : }
489 : : default :
490 : : {
491 : : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
492 : 0 : break;
493 : : }
494 : : }
495 : :
496 : : // if not the last entry, add one space to next tag
497 [ # # ]: 0 : if(a + 1UL != maList.size())
498 : : {
499 : 0 : aNewString += aEmptySpace;
500 : : }
501 : : }
502 : :
503 : : // fill string form OUString
504 : 0 : msString = aNewString;
505 : :
506 : 0 : return msString;
507 : : }
508 : :
509 : : //////////////////////////////////////////////////////////////////////////////
510 : : // sets new string, parses it and generates entries
511 : 12 : void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
512 : : {
513 : 12 : msString = rNew;
514 : 12 : EmptyList();
515 : :
516 [ + - ]: 12 : if(!msString.isEmpty())
517 : : {
518 : 12 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
519 : 12 : const sal_Int32 nLen(aStr.getLength());
520 : :
521 : 12 : const OUString aString_rotate( "rotate" );
522 : 12 : const OUString aString_scale( "scale" );
523 : 12 : const OUString aString_translate( "translate" );
524 : 12 : const OUString aString_skewX( "skewX" );
525 : 12 : const OUString aString_skewY( "skewY" );
526 : 12 : const OUString aString_matrix( "matrix" );
527 : :
528 : 12 : sal_Int32 nPos(0);
529 : :
530 [ + + ]: 36 : while(nPos < nLen)
531 : : {
532 : : // skip spaces
533 : 24 : Imp_SkipSpaces(aStr, nPos, nLen);
534 : :
535 : : // look for tag
536 [ + - ]: 24 : if(nPos < nLen)
537 : : {
538 [ + + ]: 24 : if(nPos == aStr.indexOf(aString_rotate, nPos))
539 : : {
540 : 12 : double fValue(0.0);
541 : 12 : nPos += 6;
542 : 12 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
543 [ + - ]: 12 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
544 [ + - ]: 12 : if(fValue != 0.0)
545 [ + - ][ + - ]: 12 : maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue));
546 : :
547 : 12 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
548 : : }
549 [ - + ]: 12 : else if(nPos == aStr.indexOf(aString_scale, nPos))
550 : : {
551 : 0 : ::basegfx::B2DTuple aValue(1.0, 1.0);
552 : 0 : nPos += 5;
553 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
554 [ # # ]: 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
555 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
556 [ # # ]: 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
557 : :
558 [ # # ][ # # ]: 0 : if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
[ # # ]
559 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue));
560 : :
561 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
562 : : }
563 [ + - ]: 12 : else if(nPos == aStr.indexOf(aString_translate, nPos))
564 : : {
565 : 12 : ::basegfx::B2DTuple aValue;
566 : 12 : nPos += 9;
567 : 12 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
568 [ + - ]: 12 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
569 : 12 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
570 [ + - ]: 12 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
571 : :
572 [ + - ][ + - ]: 12 : if(!aValue.equalZero())
573 [ + - ][ + - ]: 12 : maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue));
574 : :
575 : 12 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
576 : : }
577 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_skewX, nPos))
578 : : {
579 : 0 : double fValue(0.0);
580 : 0 : nPos += 5;
581 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
582 [ # # ]: 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
583 [ # # ]: 0 : if(fValue != 0.0)
584 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue));
585 : :
586 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
587 : : }
588 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_skewY, nPos))
589 : : {
590 : 0 : double fValue(0.0);
591 : 0 : nPos += 5;
592 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
593 [ # # ]: 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
594 [ # # ]: 0 : if(fValue != 0.0)
595 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue));
596 : :
597 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
598 : : }
599 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_matrix, nPos))
600 : : {
601 [ # # ]: 0 : ::basegfx::B2DHomMatrix aValue;
602 : :
603 : 0 : nPos += 6;
604 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
605 : :
606 : : // a
607 [ # # ][ # # ]: 0 : aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
[ # # ]
608 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
609 : :
610 : : // b
611 [ # # ][ # # ]: 0 : aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
[ # # ]
612 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
613 : :
614 : : // c
615 [ # # ][ # # ]: 0 : aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
[ # # ]
616 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
617 : :
618 : : // d
619 [ # # ][ # # ]: 0 : aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
[ # # ]
620 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
621 : :
622 : : // e
623 [ # # ][ # # ]: 0 : aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
[ # # ]
624 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
625 : :
626 : : // f
627 [ # # ][ # # ]: 0 : aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
[ # # ]
628 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
629 : :
630 [ # # ][ # # ]: 0 : if(!aValue.isIdentity())
631 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue));
[ # # ]
632 : :
633 [ # # ]: 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
634 : : }
635 : : else
636 : : {
637 : 0 : nPos++;
638 : : }
639 : : }
640 : 12 : }
641 : : }
642 : 12 : }
643 : :
644 : 12 : void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans)
645 : : {
646 : 12 : rFullTrans.identity();
647 : :
648 : 12 : const sal_uInt32 nCount = maList.size();
649 [ + + ]: 36 : for(sal_uInt32 a(0L); a < nCount; a++)
650 : : {
651 : 24 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
652 [ + - + - : 24 : switch(pObj->mnType)
- - - ]
653 : : {
654 : : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
655 : : {
656 : : // #i78696#
657 : : // mfRotate is mathematically wrong oriented since we export/import the angle
658 : : // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
659 : : // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
660 : : // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
661 : : // to mirror the value here
662 : 12 : rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0);
663 : 12 : break;
664 : : }
665 : : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
666 : : {
667 : 0 : const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale;
668 : 0 : rFullTrans.scale(rScale.getX(), rScale.getY());
669 : 0 : break;
670 : : }
671 : : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
672 : : {
673 : 12 : const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate;
674 : 12 : rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
675 : 12 : break;
676 : : }
677 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
678 : : {
679 : 0 : rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX));
680 : 0 : break;
681 : : }
682 : : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
683 : : {
684 : 0 : rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY));
685 : 0 : break;
686 : : }
687 : : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
688 : : {
689 : 0 : rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix;
690 : 0 : break;
691 : : }
692 : : default :
693 : : {
694 : : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
695 : 0 : break;
696 : : }
697 : : }
698 : : }
699 : 12 : }
700 : :
701 : : //////////////////////////////////////////////////////////////////////////////
702 : : //////////////////////////////////////////////////////////////////////////////
703 : : // base class of all 3D transform objects
704 : :
705 : : struct ImpSdXMLExpTransObj3DBase
706 : : {
707 : : sal_uInt16 mnType;
708 : 0 : ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
709 : 0 : : mnType(nType) {}
710 : : };
711 : :
712 : : //////////////////////////////////////////////////////////////////////////////
713 : : // possible object types for 3D
714 : :
715 : : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000
716 : : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001
717 : : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002
718 : : #define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003
719 : : #define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004
720 : : #define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005
721 : :
722 : : //////////////////////////////////////////////////////////////////////////////
723 : : // classes of objects, different sizes
724 : :
725 : : struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
726 : : {
727 : : double mfRotateX;
728 : 0 : ImpSdXMLExpTransObj3DRotateX(double fVal)
729 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {}
730 : : };
731 : : struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
732 : : {
733 : : double mfRotateY;
734 : 0 : ImpSdXMLExpTransObj3DRotateY(double fVal)
735 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {}
736 : : };
737 : : struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
738 : : {
739 : : double mfRotateZ;
740 : 0 : ImpSdXMLExpTransObj3DRotateZ(double fVal)
741 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {}
742 : : };
743 : 0 : struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
744 : : {
745 : : ::basegfx::B3DTuple maScale;
746 : 0 : ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
747 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {}
748 : : };
749 : 0 : struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
750 : : {
751 : : ::basegfx::B3DTuple maTranslate;
752 : 0 : ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
753 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {}
754 : : };
755 : 0 : struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
756 : : {
757 : : ::basegfx::B3DHomMatrix maMatrix;
758 : 0 : ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
759 : 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {}
760 : : };
761 : :
762 : : //////////////////////////////////////////////////////////////////////////////
763 : : //////////////////////////////////////////////////////////////////////////////
764 : : // delete all entries in list
765 : :
766 : 0 : void SdXMLImExTransform3D::EmptyList()
767 : : {
768 : 0 : const sal_uInt32 nCount = maList.size();
769 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nCount; a++)
770 : : {
771 : 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
772 : :
773 [ # # # # : 0 : switch(pObj->mnType)
# # # ]
774 : : {
775 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
776 : : {
777 : 0 : delete (ImpSdXMLExpTransObj3DRotateX*)pObj;
778 : 0 : break;
779 : : }
780 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
781 : : {
782 : 0 : delete (ImpSdXMLExpTransObj3DRotateY*)pObj;
783 : 0 : break;
784 : : }
785 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
786 : : {
787 : 0 : delete (ImpSdXMLExpTransObj3DRotateZ*)pObj;
788 : 0 : break;
789 : : }
790 : : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
791 : : {
792 [ # # ]: 0 : delete (ImpSdXMLExpTransObj3DScale*)pObj;
793 : 0 : break;
794 : : }
795 : : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
796 : : {
797 [ # # ]: 0 : delete (ImpSdXMLExpTransObj3DTranslate*)pObj;
798 : 0 : break;
799 : : }
800 : : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
801 : : {
802 [ # # ]: 0 : delete (ImpSdXMLExpTransObj3DMatrix*)pObj;
803 : 0 : break;
804 : : }
805 : : default :
806 : : {
807 : : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
808 : 0 : break;
809 : : }
810 : : }
811 : : }
812 : :
813 : 0 : maList.clear();
814 : 0 : }
815 : :
816 : : //////////////////////////////////////////////////////////////////////////////
817 : : // add members
818 : :
819 : 0 : void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
820 : : {
821 [ # # ]: 0 : if(!rNew.isIdentity())
822 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew));
823 : 0 : }
824 : :
825 : 0 : void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
826 : : {
827 [ # # ]: 0 : ::basegfx::B3DHomMatrix aExportMatrix;
828 : :
829 [ # # ]: 0 : aExportMatrix.set(0, 0, xHomMat.Line1.Column1);
830 [ # # ]: 0 : aExportMatrix.set(0, 1, xHomMat.Line1.Column2);
831 [ # # ]: 0 : aExportMatrix.set(0, 2, xHomMat.Line1.Column3);
832 [ # # ]: 0 : aExportMatrix.set(0, 3, xHomMat.Line1.Column4);
833 [ # # ]: 0 : aExportMatrix.set(1, 0, xHomMat.Line2.Column1);
834 [ # # ]: 0 : aExportMatrix.set(1, 1, xHomMat.Line2.Column2);
835 [ # # ]: 0 : aExportMatrix.set(1, 2, xHomMat.Line2.Column3);
836 [ # # ]: 0 : aExportMatrix.set(1, 3, xHomMat.Line2.Column4);
837 [ # # ]: 0 : aExportMatrix.set(2, 0, xHomMat.Line3.Column1);
838 [ # # ]: 0 : aExportMatrix.set(2, 1, xHomMat.Line3.Column2);
839 [ # # ]: 0 : aExportMatrix.set(2, 2, xHomMat.Line3.Column3);
840 [ # # ]: 0 : aExportMatrix.set(2, 3, xHomMat.Line3.Column4);
841 : :
842 [ # # ][ # # ]: 0 : AddMatrix(aExportMatrix);
843 : 0 : }
844 : :
845 : : //////////////////////////////////////////////////////////////////////////////
846 : : // gen string for export
847 : 0 : const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv)
848 : : {
849 : 0 : OUString aNewString;
850 : 0 : OUString aClosingBrace(sal_Unicode(')'));
851 : 0 : OUString aEmptySpace(sal_Unicode(' '));
852 : :
853 : 0 : const sal_uInt32 nCount = maList.size();
854 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nCount; a++)
855 : : {
856 : 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
857 [ # # # # : 0 : switch(pObj->mnType)
# # # ]
858 : : {
859 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
860 : : {
861 : 0 : aNewString += OUString( "rotatex (" );
862 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX);
863 : 0 : aNewString += aClosingBrace;
864 : 0 : break;
865 : : }
866 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
867 : : {
868 : 0 : aNewString += OUString( "rotatey (" );
869 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY);
870 : 0 : aNewString += aClosingBrace;
871 : 0 : break;
872 : : }
873 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
874 : : {
875 : 0 : aNewString += OUString( "rotatez (" );
876 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
877 : 0 : aNewString += aClosingBrace;
878 : 0 : break;
879 : : }
880 : : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
881 : : {
882 : 0 : aNewString += OUString( "scale (" );
883 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX());
884 : 0 : aNewString += aEmptySpace;
885 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY());
886 : 0 : aNewString += aEmptySpace;
887 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ());
888 : 0 : aNewString += aClosingBrace;
889 : 0 : break;
890 : : }
891 : : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
892 : : {
893 : 0 : aNewString += OUString( "translate (" );
894 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true);
895 : 0 : aNewString += aEmptySpace;
896 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true);
897 : 0 : aNewString += aEmptySpace;
898 [ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true);
899 : 0 : aNewString += aClosingBrace;
900 : 0 : break;
901 : : }
902 : : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
903 : : {
904 : 0 : aNewString += OUString( "matrix (" );
905 : :
906 : : // a
907 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0));
908 : 0 : aNewString += aEmptySpace;
909 : :
910 : : // b
911 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0));
912 : 0 : aNewString += aEmptySpace;
913 : :
914 : : // c
915 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0));
916 : 0 : aNewString += aEmptySpace;
917 : :
918 : : // d
919 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1));
920 : 0 : aNewString += aEmptySpace;
921 : :
922 : : // e
923 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1));
924 : 0 : aNewString += aEmptySpace;
925 : :
926 : : // f
927 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1));
928 : 0 : aNewString += aEmptySpace;
929 : :
930 : : // g
931 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2));
932 : 0 : aNewString += aEmptySpace;
933 : :
934 : : // h
935 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2));
936 : 0 : aNewString += aEmptySpace;
937 : :
938 : : // i
939 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2));
940 : 0 : aNewString += aEmptySpace;
941 : :
942 : : // j
943 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true);
944 : 0 : aNewString += aEmptySpace;
945 : :
946 : : // k
947 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true);
948 : 0 : aNewString += aEmptySpace;
949 : :
950 : : // l
951 [ # # ][ # # ]: 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true);
952 : :
953 : 0 : aNewString += aClosingBrace;
954 : 0 : break;
955 : : }
956 : : default :
957 : : {
958 : : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
959 : 0 : break;
960 : : }
961 : : }
962 : :
963 : : // if not the last entry, add one space to next tag
964 [ # # ]: 0 : if(a + 1UL != maList.size())
965 : : {
966 : 0 : aNewString += aEmptySpace;
967 : : }
968 : : }
969 : :
970 : : // fill string form OUString
971 : 0 : msString = aNewString;
972 : :
973 : 0 : return msString;
974 : : }
975 : :
976 : : //////////////////////////////////////////////////////////////////////////////
977 : : // for Import: constructor with string, parses it and generates entries
978 : 0 : SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv)
979 : : {
980 [ # # ]: 0 : SetString(rNew, rConv);
981 : 0 : }
982 : :
983 : : //////////////////////////////////////////////////////////////////////////////
984 : : // sets new string, parses it and generates entries
985 : 0 : void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
986 : : {
987 : 0 : msString = rNew;
988 : 0 : EmptyList();
989 : :
990 [ # # ]: 0 : if(!msString.isEmpty())
991 : : {
992 : 0 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
993 : 0 : const sal_Int32 nLen(aStr.getLength());
994 : :
995 : 0 : const OUString aString_rotatex( "rotatex" );
996 : 0 : const OUString aString_rotatey( "rotatey" );
997 : 0 : const OUString aString_rotatez( "rotatez" );
998 : 0 : const OUString aString_scale( "scale" );
999 : 0 : const OUString aString_translate( "translate" );
1000 : 0 : const OUString aString_matrix( "matrix" );
1001 : :
1002 : 0 : sal_Int32 nPos(0);
1003 : :
1004 [ # # ]: 0 : while(nPos < nLen)
1005 : : {
1006 : : // skip spaces
1007 : 0 : Imp_SkipSpaces(aStr, nPos, nLen);
1008 : :
1009 : : // look for tag
1010 [ # # ]: 0 : if(nPos < nLen)
1011 : : {
1012 [ # # ]: 0 : if(nPos == aStr.indexOf(aString_rotatex, nPos))
1013 : : {
1014 : 0 : double fValue(0.0);
1015 : :
1016 : 0 : nPos += 7;
1017 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1018 [ # # ]: 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1019 [ # # ]: 0 : if(fValue != 0.0)
1020 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue));
1021 : :
1022 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1023 : : }
1024 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_rotatey, nPos))
1025 : : {
1026 : 0 : double fValue(0.0);
1027 : :
1028 : 0 : nPos += 7;
1029 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1030 [ # # ]: 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1031 [ # # ]: 0 : if(fValue != 0.0)
1032 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue));
1033 : :
1034 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1035 : : }
1036 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_rotatez, nPos))
1037 : : {
1038 : 0 : double fValue(0.0);
1039 : :
1040 : 0 : nPos += 7;
1041 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1042 [ # # ]: 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1043 [ # # ]: 0 : if(fValue != 0.0)
1044 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue));
1045 : :
1046 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1047 : : }
1048 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_scale, nPos))
1049 : : {
1050 : 0 : ::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
1051 : :
1052 : 0 : nPos += 5;
1053 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1054 [ # # ]: 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
1055 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1056 [ # # ]: 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
1057 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1058 [ # # ]: 0 : aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
1059 : :
1060 [ # # ][ # # ]: 0 : if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
[ # # ][ # # ]
1061 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue));
1062 : :
1063 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1064 : : }
1065 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_translate, nPos))
1066 : : {
1067 : 0 : ::basegfx::B3DTuple aValue;
1068 : :
1069 : 0 : nPos += 9;
1070 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1071 [ # # ]: 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
1072 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1073 [ # # ]: 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
1074 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1075 [ # # ]: 0 : aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
1076 : :
1077 [ # # ][ # # ]: 0 : if(!aValue.equalZero())
1078 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue));
1079 : :
1080 : 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1081 : : }
1082 [ # # ]: 0 : else if(nPos == aStr.indexOf(aString_matrix, nPos))
1083 : : {
1084 [ # # ]: 0 : ::basegfx::B3DHomMatrix aValue;
1085 : :
1086 : 0 : nPos += 6;
1087 : 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1088 : :
1089 : : // a
1090 [ # # ][ # # ]: 0 : aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
[ # # ]
1091 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1092 : :
1093 : : // b
1094 [ # # ][ # # ]: 0 : aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
[ # # ]
1095 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1096 : :
1097 : : // c
1098 [ # # ][ # # ]: 0 : aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
[ # # ]
1099 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1100 : :
1101 : : // d
1102 [ # # ][ # # ]: 0 : aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
[ # # ]
1103 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1104 : :
1105 : : // e
1106 [ # # ][ # # ]: 0 : aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
[ # # ]
1107 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1108 : :
1109 : : // f
1110 [ # # ][ # # ]: 0 : aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
[ # # ]
1111 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1112 : :
1113 : : // g
1114 [ # # ][ # # ]: 0 : aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
[ # # ]
1115 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1116 : :
1117 : : // h
1118 [ # # ][ # # ]: 0 : aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
[ # # ]
1119 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1120 : :
1121 : : // i
1122 [ # # ][ # # ]: 0 : aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
[ # # ]
1123 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1124 : :
1125 : : // j
1126 [ # # ][ # # ]: 0 : aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
[ # # ]
1127 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1128 : :
1129 : : // k
1130 [ # # ][ # # ]: 0 : aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
[ # # ]
1131 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1132 : :
1133 : : // l
1134 [ # # ][ # # ]: 0 : aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
[ # # ]
1135 : 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1136 : :
1137 [ # # ][ # # ]: 0 : if(!aValue.isIdentity())
1138 [ # # ][ # # ]: 0 : maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue));
[ # # ]
1139 : :
1140 [ # # ]: 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1141 : : }
1142 : : else
1143 : : {
1144 : 0 : nPos++;
1145 : : }
1146 : : }
1147 : 0 : }
1148 : : }
1149 : 0 : }
1150 : :
1151 : 0 : bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat)
1152 : : {
1153 [ # # ]: 0 : ::basegfx::B3DHomMatrix aFullTransform;
1154 [ # # ]: 0 : GetFullTransform(aFullTransform);
1155 : :
1156 [ # # ][ # # ]: 0 : if(!aFullTransform.isIdentity())
1157 : : {
1158 [ # # ]: 0 : xHomMat.Line1.Column1 = aFullTransform.get(0, 0);
1159 [ # # ]: 0 : xHomMat.Line1.Column2 = aFullTransform.get(0, 1);
1160 [ # # ]: 0 : xHomMat.Line1.Column3 = aFullTransform.get(0, 2);
1161 [ # # ]: 0 : xHomMat.Line1.Column4 = aFullTransform.get(0, 3);
1162 : :
1163 [ # # ]: 0 : xHomMat.Line2.Column1 = aFullTransform.get(1, 0);
1164 [ # # ]: 0 : xHomMat.Line2.Column2 = aFullTransform.get(1, 1);
1165 [ # # ]: 0 : xHomMat.Line2.Column3 = aFullTransform.get(1, 2);
1166 [ # # ]: 0 : xHomMat.Line2.Column4 = aFullTransform.get(1, 3);
1167 : :
1168 [ # # ]: 0 : xHomMat.Line3.Column1 = aFullTransform.get(2, 0);
1169 [ # # ]: 0 : xHomMat.Line3.Column2 = aFullTransform.get(2, 1);
1170 [ # # ]: 0 : xHomMat.Line3.Column3 = aFullTransform.get(2, 2);
1171 [ # # ]: 0 : xHomMat.Line3.Column4 = aFullTransform.get(2, 3);
1172 : :
1173 [ # # ]: 0 : xHomMat.Line4.Column1 = aFullTransform.get(3, 0);
1174 [ # # ]: 0 : xHomMat.Line4.Column2 = aFullTransform.get(3, 1);
1175 [ # # ]: 0 : xHomMat.Line4.Column3 = aFullTransform.get(3, 2);
1176 [ # # ]: 0 : xHomMat.Line4.Column4 = aFullTransform.get(3, 3);
1177 : :
1178 : 0 : return true;
1179 : : }
1180 : :
1181 [ # # ]: 0 : return false;
1182 : : }
1183 : :
1184 : 0 : void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
1185 : : {
1186 : 0 : rFullTrans.identity();
1187 : :
1188 : 0 : const sal_uInt32 nCount = maList.size();
1189 [ # # ]: 0 : for(sal_uInt32 a(0L); a < nCount; a++)
1190 : : {
1191 : 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
1192 [ # # # # : 0 : switch(pObj->mnType)
# # # ]
1193 : : {
1194 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
1195 : : {
1196 : 0 : rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0);
1197 : 0 : break;
1198 : : }
1199 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
1200 : : {
1201 : 0 : rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0);
1202 : 0 : break;
1203 : : }
1204 : : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
1205 : : {
1206 : 0 : rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
1207 : 0 : break;
1208 : : }
1209 : : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
1210 : : {
1211 : 0 : const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale;
1212 : 0 : rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
1213 : 0 : break;
1214 : : }
1215 : : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
1216 : : {
1217 : 0 : const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate;
1218 : 0 : rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
1219 : 0 : break;
1220 : : }
1221 : : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
1222 : : {
1223 : 0 : rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix;
1224 : 0 : break;
1225 : : }
1226 : : default :
1227 : : {
1228 : : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
1229 : 0 : break;
1230 : : }
1231 : : }
1232 : : }
1233 : 0 : }
1234 : :
1235 : : //////////////////////////////////////////////////////////////////////////////
1236 : : //////////////////////////////////////////////////////////////////////////////
1237 : :
1238 : 12 : SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH)
1239 : : : mnX( nX ),
1240 : : mnY( nY ),
1241 : : mnW( nW ),
1242 : 12 : mnH( nH )
1243 : : {
1244 : 12 : }
1245 : :
1246 : : // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
1247 : 389 : SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
1248 : : : msString(rNew),
1249 : : mnX( 0L ),
1250 : : mnY( 0L ),
1251 : : mnW( 1000L ),
1252 : 389 : mnH( 1000L )
1253 : : {
1254 [ + - ]: 389 : if(!msString.isEmpty())
1255 : : {
1256 : 389 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1257 : 389 : const sal_Int32 nLen(aStr.getLength());
1258 : 389 : sal_Int32 nPos(0);
1259 : :
1260 : : // skip starting spaces
1261 : 389 : Imp_SkipSpaces(aStr, nPos, nLen);
1262 : :
1263 : : // get mX, #100617# be prepared for doubles
1264 [ + - ]: 389 : mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX));
1265 : :
1266 : : // skip spaces and commas
1267 : 389 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1268 : :
1269 : : // get mY, #100617# be prepared for doubles
1270 [ + - ]: 389 : mnY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnY));
1271 : :
1272 : : // skip spaces and commas
1273 : 389 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1274 : :
1275 : : // get mW, #100617# be prepared for doubles
1276 [ + - ]: 389 : mnW = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnW));
1277 : :
1278 : : // skip spaces and commas
1279 : 389 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1280 : :
1281 : : // get mH, #100617# be prepared for doubles
1282 [ + - ]: 389 : mnH = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnH));
1283 : : }
1284 : 389 : }
1285 : :
1286 : 12 : const OUString& SdXMLImExViewBox::GetExportString()
1287 : : {
1288 : 12 : OUString aNewString;
1289 : 12 : OUString aEmptySpace(sal_Unicode(' '));
1290 : :
1291 [ + - ]: 12 : Imp_PutNumberChar(aNewString, mnX);
1292 : 12 : aNewString += aEmptySpace;
1293 : :
1294 [ + - ]: 12 : Imp_PutNumberChar(aNewString, mnY);
1295 : 12 : aNewString += aEmptySpace;
1296 : :
1297 [ + - ]: 12 : Imp_PutNumberChar(aNewString, mnW);
1298 : 12 : aNewString += aEmptySpace;
1299 : :
1300 [ + - ]: 12 : Imp_PutNumberChar(aNewString, mnH);
1301 : :
1302 : : // set new string
1303 : 12 : msString = aNewString;
1304 : :
1305 : 12 : return msString;
1306 : : }
1307 : :
1308 : : //////////////////////////////////////////////////////////////////////////////
1309 : : //////////////////////////////////////////////////////////////////////////////
1310 : :
1311 : 0 : SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints,
1312 : : const SdXMLImExViewBox& rViewBox,
1313 : : const awt::Point& rObjectPos,
1314 : : const awt::Size& rObjectSize,
1315 : : // #96328#
1316 : : const bool bClosed)
1317 [ # # ]: 0 : : maPoly( 0L )
1318 : : {
1319 : : DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
1320 : :
1321 : : // add polygon to string
1322 : 0 : sal_Int32 nCnt(pPoints->getLength());
1323 : :
1324 : : // #104076# Convert to string only when at last one point included
1325 [ # # ]: 0 : if(nCnt > 0)
1326 : : {
1327 : 0 : OUString aNewString;
1328 [ # # ]: 0 : awt::Point* pArray = pPoints->getArray();
1329 : :
1330 : : // last point same? Ignore it.
1331 : : // #96328# ...but only when polygon is CLOSED
1332 [ # # ][ # # ]: 0 : if(bClosed && (pArray->X == (pArray + (nCnt - 1))->X) && (pArray->Y == (pArray + (nCnt - 1))->Y))
[ # # ]
1333 : 0 : nCnt--;
1334 : :
1335 : : // object size and ViewBox size different?
1336 : 0 : bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1337 [ # # ][ # # ]: 0 : || rObjectSize.Height != rViewBox.GetHeight());
1338 [ # # ][ # # ]: 0 : bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1339 : :
1340 [ # # ]: 0 : for(sal_Int32 a(0L); a < nCnt; a++)
1341 : : {
1342 : : // prepare coordinates
1343 : 0 : sal_Int32 nX( pArray->X - rObjectPos.X );
1344 : 0 : sal_Int32 nY( pArray->Y - rObjectPos.Y );
1345 : :
1346 [ # # ][ # # ]: 0 : if(bScale && rObjectSize.Width && rObjectSize.Height)
[ # # ]
1347 : : {
1348 : 0 : nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width;
1349 : 0 : nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height;
1350 : : }
1351 : :
1352 [ # # ]: 0 : if(bTranslate)
1353 : : {
1354 : 0 : nX += rViewBox.GetX();
1355 : 0 : nY += rViewBox.GetY();
1356 : : }
1357 : :
1358 : : // X and comma
1359 [ # # ]: 0 : Imp_PutNumberChar(aNewString, nX);
1360 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>(','));
1361 : :
1362 : : // Y and space (not for last)
1363 [ # # ]: 0 : Imp_PutNumberChar(aNewString, nY);
1364 [ # # ]: 0 : if(a + 1 != nCnt)
1365 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>(' '));
1366 : :
1367 : : // next point
1368 : 0 : pArray++;
1369 : : }
1370 : :
1371 : : // set new string
1372 : 0 : msString = aNewString;
1373 : : }
1374 : 0 : }
1375 : :
1376 : : // #100617# svg:polyline or svg:polygon values may be double precision.
1377 : 12 : SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString& rNew,
1378 : : const SdXMLImExViewBox& rViewBox,
1379 : : const awt::Point& rObjectPos,
1380 : : const awt::Size& rObjectSize,
1381 : : const SvXMLUnitConverter& rConv)
1382 : : : msString( rNew ),
1383 [ + - ]: 12 : maPoly( 0L )
1384 : : {
1385 : : // convert string to polygon
1386 : 12 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1387 : 12 : const sal_Int32 nLen(aStr.getLength());
1388 : 12 : sal_Int32 nPos(0);
1389 : 12 : sal_Int32 nNumPoints(0L);
1390 : :
1391 : : // skip starting spaces
1392 : 12 : Imp_SkipSpaces(aStr, nPos, nLen);
1393 : :
1394 : : // count points in first loop
1395 [ + + ]: 132 : while(nPos < nLen)
1396 : : {
1397 : : // skip number, #100617# be prepared for doubles
1398 : 120 : Imp_SkipDouble(aStr, nPos, nLen);
1399 : :
1400 : : // skip spaces and commas
1401 : 120 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1402 : :
1403 : : // skip number, #100617# be prepared for doubles
1404 : 120 : Imp_SkipDouble(aStr, nPos, nLen);
1405 : :
1406 : : // skip spaces and commas
1407 : 120 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1408 : :
1409 : : // one more point
1410 : 120 : nNumPoints++;
1411 : : }
1412 : :
1413 : : // second loop
1414 [ + - ]: 12 : if(nNumPoints)
1415 : : {
1416 : 12 : nPos = 0;
1417 [ + - ]: 12 : maPoly.realloc(1);
1418 [ + - ]: 12 : drawing::PointSequence* pOuterSequence = maPoly.getArray();
1419 [ + - ]: 12 : pOuterSequence->realloc(nNumPoints);
1420 [ + - ]: 12 : awt::Point* pInnerSequence = pOuterSequence->getArray();
1421 : :
1422 : : // object size and ViewBox size different?
1423 : 12 : bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1424 [ - + ][ + - ]: 12 : || rObjectSize.Height != rViewBox.GetHeight());
1425 [ + - ][ - + ]: 12 : bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1426 : :
1427 : : // skip starting spaces
1428 : 12 : Imp_SkipSpaces(aStr, nPos, nLen);
1429 : :
1430 [ + + ]: 132 : while(nPos < nLen)
1431 : : {
1432 : : // prepare new parameter pair
1433 : 120 : sal_Int32 nX(0L);
1434 : 120 : sal_Int32 nY(0L);
1435 : :
1436 : : // get mX, #100617# be prepared for doubles
1437 [ + - ]: 120 : nX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nX));
1438 : :
1439 : : // skip spaces and commas
1440 : 120 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1441 : :
1442 : : // get mY, #100617# be prepared for doubles
1443 [ + - ]: 120 : nY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nY));
1444 : :
1445 : : // skip spaces and commas
1446 : 120 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1447 : :
1448 : : // prepare parameters
1449 [ - + ]: 120 : if(bTranslate)
1450 : : {
1451 : 0 : nX -= rViewBox.GetX();
1452 : 0 : nY -= rViewBox.GetY();
1453 : : }
1454 : :
1455 [ - + ][ # # ]: 120 : if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight() )
[ # # ][ - + ]
1456 : : {
1457 : 0 : nX = (nX * rObjectSize.Width) / rViewBox.GetWidth();
1458 : 0 : nY = (nY * rObjectSize.Height) / rViewBox.GetHeight();
1459 : : }
1460 : :
1461 : 120 : nX += rObjectPos.X;
1462 : 120 : nY += rObjectPos.Y;
1463 : :
1464 : : // add new point
1465 : 120 : *pInnerSequence = awt::Point( nX, nY );
1466 : 120 : pInnerSequence++;
1467 : : }
1468 : 12 : }
1469 : 12 : }
1470 : :
1471 : : //////////////////////////////////////////////////////////////////////////////
1472 : : //////////////////////////////////////////////////////////////////////////////
1473 : :
1474 : 12 : SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox,
1475 : : const SvXMLExport& rExport)
1476 : : : mrViewBox( rViewBox ),
1477 : : mbIsClosed( false ),
1478 : : mbIsCurve( false ),
1479 : : // fdo#47406 - handle writing svg:d path slightly different for
1480 : : // old odf versions and ODF1.2 compat mode - since ~all the legacy
1481 : : // ODF ecosystem interprets relative svg:d paths incorrectly,
1482 : : // write out absolute paths in those cases.
1483 [ + - ]: 12 : mbRelative( rExport.getDefaultVersion() >= SvtSaveOptions::ODFVER_012 &&
1484 [ + - ]: 12 : rExport.getDefaultVersion() != SvtSaveOptions::ODFVER_012_EXT_COMPAT ),
1485 : : mnLastX( 0L ),
1486 : : mnLastY( 0L ),
1487 [ + - ][ + - ]: 36 : maPoly()
[ + - ]
1488 : : {
1489 : 12 : }
1490 : :
1491 : 0 : void Imp_GetPrevPos(awt::Point*& pPrevPos1,
1492 : : drawing::PolygonFlags& aPrevFlag1,
1493 : : const bool bClosed, awt::Point* pPoints,
1494 : : drawing::PolygonFlags* pFlags, const sal_Int32 nPos,
1495 : : const sal_Int32 nCnt, const sal_Int32 nAdd)
1496 : : {
1497 [ # # ]: 0 : if(bClosed)
1498 : : {
1499 : 0 : pPrevPos1 = pPoints + ((nPos + nCnt - nAdd) % nCnt);
1500 : 0 : aPrevFlag1 = *(pFlags + ((nPos + nCnt - nAdd) % nCnt));
1501 : : }
1502 [ # # ]: 0 : else if(nPos > (nAdd - 1))
1503 : : {
1504 : 0 : pPrevPos1 = pPoints + (nPos - nAdd);
1505 : 0 : aPrevFlag1 = *(pFlags + (nPos - nAdd));
1506 : : }
1507 : : else
1508 : 0 : pPrevPos1 = 0L;
1509 : 0 : }
1510 : :
1511 : 36 : void Imp_PrepareCoorExport(sal_Int32& nX, sal_Int32& nY,
1512 : : const awt::Point* pPointArray, const awt::Point& rObjectPos,
1513 : : const awt::Size& rObjectSize, const SdXMLImExViewBox& mrViewBox,
1514 : : const bool bScale, const bool bTranslate)
1515 : : {
1516 : 36 : nX = pPointArray->X - rObjectPos.X;
1517 : 36 : nY = pPointArray->Y - rObjectPos.Y;
1518 : :
1519 [ - + ][ # # ]: 36 : if(bScale && rObjectSize.Width && rObjectSize.Height )
[ # # ]
1520 : : {
1521 : 0 : nX = (nX * mrViewBox.GetWidth()) / rObjectSize.Width;
1522 : 0 : nY = (nY * mrViewBox.GetHeight()) / rObjectSize.Height;
1523 : : }
1524 : :
1525 [ - + ]: 36 : if(bTranslate)
1526 : : {
1527 : 0 : nX += mrViewBox.GetX();
1528 : 0 : nY += mrViewBox.GetY();
1529 : : }
1530 : 36 : }
1531 : :
1532 : : //#define TEST_QUADRATIC_CURVES
1533 : : #ifdef TEST_QUADRATIC_CURVES
1534 : : // To be able to test quadratic curve code: The code concerning to
1535 : : // bDoTestHere can be used (see below). Construct shapes which have their control
1536 : : // points on equal coordinates. When these are written, they can be
1537 : : // forced to create correct 'Q' and 'T' statements using this flag.
1538 : : // These may then be tested for import/exporting.
1539 : : static bool bDoTestHere(true);
1540 : : #endif // TEST_QUADRATIC_CURVES
1541 : :
1542 : 12 : void SdXMLImExSvgDElement::AddPolygon(
1543 : : drawing::PointSequence* pPoints,
1544 : : drawing::FlagSequence* pFlags,
1545 : : const awt::Point& rObjectPos,
1546 : : const awt::Size& rObjectSize,
1547 : : bool bClosed)
1548 : : {
1549 : : // Leaving the export stuff for the while, should eventually also
1550 : : // consolidated with basegfx svg support
1551 : : DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)");
1552 : :
1553 : 12 : sal_Int32 nCnt(pPoints->getLength());
1554 : :
1555 : : // #104076# Convert to string only when at last one point included
1556 [ + - ]: 12 : if(nCnt > 0)
1557 : : {
1558 : : // append polygon to string
1559 : 12 : OUString aNewString;
1560 : 12 : sal_Unicode aLastCommand = ' ';
1561 [ + - ]: 12 : awt::Point* pPointArray = pPoints->getArray();
1562 : :
1563 : : // are the flags used at all? If not forget about them
1564 [ + - ]: 12 : if(pFlags)
1565 : : {
1566 : 12 : sal_Int32 nFlagCnt(pFlags->getLength());
1567 : :
1568 [ + - ]: 12 : if(nFlagCnt)
1569 : : {
1570 : 12 : bool bFlagsUsed(false);
1571 [ + - ]: 12 : drawing::PolygonFlags* pFlagArray = pFlags->getArray();
1572 : :
1573 [ + - ][ + + ]: 60 : for(sal_Int32 a(0); !bFlagsUsed && a < nFlagCnt; a++)
[ + + ]
1574 [ - + ]: 48 : if(drawing::PolygonFlags_NORMAL != *pFlagArray++)
1575 : 0 : bFlagsUsed = true;
1576 : :
1577 [ + - ]: 12 : if(!bFlagsUsed)
1578 : 12 : pFlags = 0L;
1579 : : }
1580 : : else
1581 : : {
1582 : 0 : pFlags = 0L;
1583 : : }
1584 : : }
1585 : :
1586 : : // object size and ViewBox size different?
1587 : 12 : bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
1588 [ - + ][ + - ]: 12 : || rObjectSize.Height != mrViewBox.GetHeight());
1589 [ + - ][ - + ]: 12 : bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
1590 : :
1591 : : // #87202# rework of point reduction:
1592 : : // Test for Last point same -> closed, ignore last point. Take
1593 : : // some more circumstances in account when looking at curve segments.
1594 [ - + ][ # # ]: 12 : drawing::PolygonFlags* pFlagArray = (pFlags) ? pFlags->getArray() : 0L;
1595 [ + - ][ + - ]: 12 : if((pPointArray->X == (pPointArray + (nCnt - 1))->X) && (pPointArray->Y == (pPointArray + (nCnt - 1))->Y))
1596 : : {
1597 [ - + ]: 12 : if(pFlags)
1598 : : {
1599 : : // point needs to be ignored if point before it is
1600 : : // NO control point. Else the last point is needed
1601 : : // for exporting the last segment of the curve. That means
1602 : : // that the last and the first point will be saved double,
1603 : : // but SVG does not support a better solution here.
1604 [ # # ][ # # ]: 0 : if(nCnt >= 2 && drawing::PolygonFlags_CONTROL != *(pFlagArray + (nCnt - 2)))
1605 : : {
1606 : 0 : nCnt--;
1607 : : }
1608 : : }
1609 : : else
1610 : : {
1611 : : // no curve, ignore last point
1612 : 12 : nCnt--;
1613 : : }
1614 : : }
1615 : :
1616 : : // bezier poly, handle curves
1617 : 12 : bool bDidWriteStart(false);
1618 : 12 : sal_Int32 nStartX(0), nStartY(0);
1619 : :
1620 [ + + ]: 48 : for(sal_Int32 a(0L); a < nCnt; a++)
1621 : : {
1622 [ - + ][ # # ]: 36 : if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray)
1623 : : {
1624 : 36 : bool bDidWriteAsCurve(false);
1625 : :
1626 [ + + ]: 36 : if(bDidWriteStart)
1627 : : {
1628 [ - + ]: 24 : if(pFlags)
1629 : : {
1630 : : // real curve point, get previous to see if it's a control point
1631 : : awt::Point* pPrevPos1;
1632 : : drawing::PolygonFlags aPrevFlag1;
1633 : :
1634 : : Imp_GetPrevPos(pPrevPos1, aPrevFlag1, bClosed, pPoints->getArray(),
1635 [ # # ][ # # ]: 0 : pFlags->getArray(), a, nCnt, 1);
1636 : :
1637 [ # # ][ # # ]: 0 : if(pPrevPos1 && drawing::PolygonFlags_CONTROL == aPrevFlag1)
1638 : : {
1639 : : // get previous2 to see if it's a control point, too
1640 : : awt::Point* pPrevPos2;
1641 : : drawing::PolygonFlags aPrevFlag2;
1642 : :
1643 : : Imp_GetPrevPos(pPrevPos2, aPrevFlag2, bClosed, pPoints->getArray(),
1644 [ # # ][ # # ]: 0 : pFlags->getArray(), a, nCnt, 2);
1645 : :
1646 [ # # ][ # # ]: 0 : if(pPrevPos2 && drawing::PolygonFlags_CONTROL == aPrevFlag2)
1647 : : {
1648 : : // get previous3 to see if it's a curve point and if,
1649 : : // if it is fully symmetric or not
1650 : : awt::Point* pPrevPos3;
1651 : : drawing::PolygonFlags aPrevFlag3;
1652 : :
1653 : : Imp_GetPrevPos(pPrevPos3, aPrevFlag3, bClosed, pPoints->getArray(),
1654 [ # # ][ # # ]: 0 : pFlags->getArray(), a, nCnt, 3);
1655 : :
1656 [ # # ]: 0 : if(pPrevPos3)
1657 : : {
1658 : : // prepare coordinates
1659 : : sal_Int32 nX, nY;
1660 : :
1661 : : Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
1662 : 0 : mrViewBox, bScale, bTranslate);
1663 : :
1664 : : // #100617# test if this curve segment may be written as
1665 : : // a quadratic bezier
1666 : : // That's the case if both control points are in the same place
1667 : : // when they are prolonged to the common quadratic control point
1668 : : // Left: P = (3P1 - P0) / 2
1669 : : // Right: P = (3P2 - P3) / 2
1670 : 0 : bool bIsQuadratic(false);
1671 : 0 : const bool bEnableSaveQuadratic(false);
1672 : :
1673 : 0 : sal_Int32 nPX_L(FRound((double)((3 * pPrevPos2->X) - pPrevPos3->X) / 2.0));
1674 : 0 : sal_Int32 nPY_L(FRound((double)((3 * pPrevPos2->Y) - pPrevPos3->Y) / 2.0));
1675 : 0 : sal_Int32 nPX_R(FRound((double)((3 * pPrevPos1->X) - pPointArray->X) / 2.0));
1676 : 0 : sal_Int32 nPY_R(FRound((double)((3 * pPrevPos1->Y) - pPointArray->Y) / 2.0));
1677 : 0 : sal_Int32 nDist(0);
1678 : :
1679 [ # # ]: 0 : if(nPX_L != nPX_R)
1680 : : {
1681 : 0 : nDist += abs(nPX_L - nPX_R);
1682 : : }
1683 : :
1684 [ # # ]: 0 : if(nPY_L != nPY_R)
1685 : : {
1686 : 0 : nDist += abs(nPY_L - nPY_R);
1687 : : }
1688 : :
1689 : : if(nDist <= BORDER_INTEGERS_ARE_EQUAL)
1690 : : {
1691 : : if(bEnableSaveQuadratic)
1692 : : {
1693 : : bIsQuadratic = true;
1694 : : }
1695 : : }
1696 : :
1697 : : #ifdef TEST_QUADRATIC_CURVES
1698 : : if(bDoTestHere)
1699 : : {
1700 : : bIsQuadratic = false;
1701 : :
1702 : : if(pPrevPos1->X == pPrevPos2->X && pPrevPos1->Y == pPrevPos2->Y)
1703 : : bIsQuadratic = true;
1704 : : }
1705 : : #endif // TEST_QUADRATIC_CURVES
1706 : :
1707 [ # # ]: 0 : if(bIsQuadratic)
1708 : : {
1709 : : #ifdef TEST_QUADRATIC_CURVES
1710 : : if(bDoTestHere)
1711 : : {
1712 : : bool bPrevPointIsSymmetric(false);
1713 : :
1714 : : if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
1715 : : {
1716 : : // get previous4 to see if it's a control point
1717 : : awt::Point* pPrevPos4;
1718 : : drawing::PolygonFlags aPrevFlag4;
1719 : :
1720 : : Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1721 : : pFlags->getArray(), a, nCnt, 4);
1722 : :
1723 : : if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1724 : : {
1725 : : // okay, prevPos3 is symmetric (c2) and prevPos4
1726 : : // is existing control point, the 's' statement can be used
1727 : : bPrevPointIsSymmetric = true;
1728 : : }
1729 : : }
1730 : :
1731 : : if(bPrevPointIsSymmetric)
1732 : : {
1733 : : // write a shorthand/smooth quadratic curveto entry (T)
1734 : : if(mbRelative)
1735 : : {
1736 : : if(aLastCommand != sal_Unicode('t'))
1737 : : aNewString += OUString(sal_Unicode('t'));
1738 : :
1739 : : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1740 : : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1741 : :
1742 : : aLastCommand = sal_Unicode('t');
1743 : : }
1744 : : else
1745 : : {
1746 : : if(aLastCommand != sal_Unicode('T'))
1747 : : aNewString += OUString(sal_Unicode('T'));
1748 : :
1749 : : Imp_PutNumberCharWithSpace(aNewString, nX);
1750 : : Imp_PutNumberCharWithSpace(aNewString, nY);
1751 : :
1752 : : aLastCommand = sal_Unicode('T');
1753 : : }
1754 : : }
1755 : : else
1756 : : {
1757 : : // prepare coordinates
1758 : : sal_Int32 nX1, nY1;
1759 : :
1760 : : Imp_PrepareCoorExport(nX1, nY1, pPrevPos1, rObjectPos, rObjectSize,
1761 : : mrViewBox, bScale, bTranslate);
1762 : :
1763 : : // write a quadratic curveto entry (Q)
1764 : : if(mbRelative)
1765 : : {
1766 : : if(aLastCommand != sal_Unicode('q'))
1767 : : aNewString += OUString(sal_Unicode('q'));
1768 : :
1769 : : Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1770 : : Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1771 : : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1772 : : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1773 : :
1774 : : aLastCommand = sal_Unicode('q');
1775 : : }
1776 : : else
1777 : : {
1778 : : if(aLastCommand != sal_Unicode('Q'))
1779 : : aNewString += OUString(sal_Unicode('Q'));
1780 : :
1781 : : Imp_PutNumberCharWithSpace(aNewString, nX1);
1782 : : Imp_PutNumberCharWithSpace(aNewString, nY1);
1783 : : Imp_PutNumberCharWithSpace(aNewString, nX);
1784 : : Imp_PutNumberCharWithSpace(aNewString, nY);
1785 : :
1786 : : aLastCommand = sal_Unicode('Q');
1787 : : }
1788 : : }
1789 : : }
1790 : : else
1791 : : {
1792 : : #endif // TEST_QUADRATIC_CURVES
1793 : 0 : awt::Point aNewPoint(nPX_L, nPY_L);
1794 : 0 : bool bPrevPointIsSmooth(false);
1795 : :
1796 [ # # ]: 0 : if(drawing::PolygonFlags_SMOOTH == aPrevFlag3)
1797 : : {
1798 : : // get previous4 to see if it's a control point
1799 : : awt::Point* pPrevPos4;
1800 : : drawing::PolygonFlags aPrevFlag4;
1801 : :
1802 : : Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1803 [ # # ][ # # ]: 0 : pFlags->getArray(), a, nCnt, 4);
1804 : :
1805 [ # # ]: 0 : if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1806 : : {
1807 : : // okay, prevPos3 is smooth (c1) and prevPos4
1808 : : // is existing control point. Test if it's even symmetric
1809 : : // and thus the 'T' statement may be used.
1810 : 0 : ::basegfx::B2DVector aVec1(pPrevPos4->X - pPrevPos3->X, pPrevPos4->Y - pPrevPos3->Y);
1811 : 0 : ::basegfx::B2DVector aVec2(aNewPoint.X - pPrevPos3->X, aNewPoint.Y - pPrevPos3->Y);
1812 : 0 : bool bSameLength(false);
1813 : 0 : bool bSameDirection(false);
1814 : :
1815 : : // get vector values
1816 [ # # ]: 0 : Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection);
1817 : :
1818 [ # # ][ # # ]: 0 : if(bSameLength && bSameDirection)
1819 : 0 : bPrevPointIsSmooth = true;
1820 : : }
1821 : : }
1822 : :
1823 [ # # ]: 0 : if(bPrevPointIsSmooth)
1824 : : {
1825 : : // write a shorthand/smooth quadratic curveto entry (T)
1826 [ # # ]: 0 : if(mbRelative)
1827 : : {
1828 [ # # ]: 0 : if(aLastCommand != sal_Unicode('t'))
1829 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('t'));
1830 : :
1831 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1832 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1833 : :
1834 : 0 : aLastCommand = sal_Unicode('t');
1835 : : }
1836 : : else
1837 : : {
1838 [ # # ]: 0 : if(aLastCommand != sal_Unicode('T'))
1839 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('T'));
1840 : :
1841 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
1842 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
1843 : :
1844 : 0 : aLastCommand = sal_Unicode('T');
1845 : : }
1846 : : }
1847 : : else
1848 : : {
1849 : : // prepare coordinates
1850 : : sal_Int32 nX1, nY1;
1851 : :
1852 : : Imp_PrepareCoorExport(nX1, nY1, &aNewPoint, rObjectPos, rObjectSize,
1853 : 0 : mrViewBox, bScale, bTranslate);
1854 : :
1855 : : // write a quadratic curveto entry (Q)
1856 [ # # ]: 0 : if(mbRelative)
1857 : : {
1858 [ # # ]: 0 : if(aLastCommand != sal_Unicode('q'))
1859 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('q'));
1860 : :
1861 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1862 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1863 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1864 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1865 : :
1866 : 0 : aLastCommand = sal_Unicode('q');
1867 : : }
1868 : : else
1869 : : {
1870 [ # # ]: 0 : if(aLastCommand != sal_Unicode('Q'))
1871 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('Q'));
1872 : :
1873 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX1);
1874 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY1);
1875 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
1876 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
1877 : :
1878 : 0 : aLastCommand = sal_Unicode('Q');
1879 : : }
1880 : : }
1881 : : #ifdef TEST_QUADRATIC_CURVES
1882 : : }
1883 : : #endif // TEST_QUADRATIC_CURVES
1884 : : }
1885 : : else
1886 : : {
1887 : 0 : bool bPrevPointIsSymmetric(false);
1888 : :
1889 [ # # ]: 0 : if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3)
1890 : : {
1891 : : // get previous4 to see if it's a control point
1892 : : awt::Point* pPrevPos4;
1893 : : drawing::PolygonFlags aPrevFlag4;
1894 : :
1895 : : Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(),
1896 [ # # ][ # # ]: 0 : pFlags->getArray(), a, nCnt, 4);
1897 : :
1898 [ # # ]: 0 : if(drawing::PolygonFlags_CONTROL == aPrevFlag4)
1899 : : {
1900 : : // okay, prevPos3 is symmetric (c2) and prevPos4
1901 : : // is existing control point, the 's' statement can be used
1902 : 0 : bPrevPointIsSymmetric = true;
1903 : : }
1904 : : }
1905 : :
1906 : : // prepare coordinates
1907 : : sal_Int32 nX2, nY2;
1908 : :
1909 : : Imp_PrepareCoorExport(nX2, nY2, pPrevPos1, rObjectPos, rObjectSize,
1910 : 0 : mrViewBox, bScale, bTranslate);
1911 : :
1912 [ # # ]: 0 : if(bPrevPointIsSymmetric)
1913 : : {
1914 : : // write a shorthand/smooth curveto entry (S)
1915 [ # # ]: 0 : if(mbRelative)
1916 : : {
1917 [ # # ]: 0 : if(aLastCommand != sal_Unicode('s'))
1918 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('s'));
1919 : :
1920 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
1921 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
1922 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1923 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1924 : :
1925 : 0 : aLastCommand = sal_Unicode('s');
1926 : : }
1927 : : else
1928 : : {
1929 [ # # ]: 0 : if(aLastCommand != sal_Unicode('S'))
1930 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('S'));
1931 : :
1932 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX2);
1933 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY2);
1934 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
1935 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
1936 : :
1937 : 0 : aLastCommand = sal_Unicode('S');
1938 : : }
1939 : : }
1940 : : else
1941 : : {
1942 : : // prepare coordinates
1943 : : sal_Int32 nX1, nY1;
1944 : :
1945 : : Imp_PrepareCoorExport(nX1, nY1, pPrevPos2, rObjectPos, rObjectSize,
1946 : 0 : mrViewBox, bScale, bTranslate);
1947 : :
1948 : : // write a curveto entry (C)
1949 [ # # ]: 0 : if(mbRelative)
1950 : : {
1951 [ # # ]: 0 : if(aLastCommand != sal_Unicode('c'))
1952 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('c'));
1953 : :
1954 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX);
1955 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY);
1956 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX);
1957 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY);
1958 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
1959 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
1960 : :
1961 : 0 : aLastCommand = sal_Unicode('c');
1962 : : }
1963 : : else
1964 : : {
1965 [ # # ]: 0 : if(aLastCommand != sal_Unicode('C'))
1966 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('C'));
1967 : :
1968 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX1);
1969 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY1);
1970 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX2);
1971 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY2);
1972 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
1973 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
1974 : :
1975 : 0 : aLastCommand = sal_Unicode('C');
1976 : : }
1977 : : }
1978 : : }
1979 : :
1980 : : // remember that current point IS written
1981 : 0 : bDidWriteAsCurve = true;
1982 : :
1983 : : // remember new last position
1984 : 0 : mnLastX = nX;
1985 : 0 : mnLastY = nY;
1986 : : }
1987 : : }
1988 : : }
1989 : : }
1990 : : }
1991 : :
1992 [ + - ]: 36 : if(!bDidWriteAsCurve)
1993 : : {
1994 : : // current point not yet written, prepare coordinates
1995 : : sal_Int32 nX, nY;
1996 : :
1997 : : Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize,
1998 : 36 : mrViewBox, bScale, bTranslate);
1999 : :
2000 [ + + ]: 36 : if(bDidWriteStart)
2001 : : {
2002 : : // write as normal point
2003 [ - + ]: 24 : if(mnLastX == nX)
2004 : : {
2005 [ # # ]: 0 : if(mbRelative)
2006 : : {
2007 [ # # ]: 0 : if(aLastCommand != sal_Unicode('v'))
2008 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('v'));
2009 : :
2010 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2011 : :
2012 : 0 : aLastCommand = sal_Unicode('v');
2013 : : }
2014 : : else
2015 : : {
2016 [ # # ]: 0 : if(aLastCommand != sal_Unicode('V'))
2017 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('V'));
2018 : :
2019 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
2020 : :
2021 : 0 : aLastCommand = sal_Unicode('V');
2022 : : }
2023 : : }
2024 [ + + ]: 24 : else if(mnLastY == nY)
2025 : : {
2026 [ + - ]: 12 : if(mbRelative)
2027 : : {
2028 [ + - ]: 12 : if(aLastCommand != sal_Unicode('h'))
2029 : 12 : aNewString += rtl::OUString(static_cast<sal_Unicode>('h'));
2030 : :
2031 [ + - ]: 12 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2032 : :
2033 : 12 : aLastCommand = sal_Unicode('h');
2034 : : }
2035 : : else
2036 : : {
2037 [ # # ]: 0 : if(aLastCommand != sal_Unicode('H'))
2038 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('H'));
2039 : :
2040 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
2041 : :
2042 : 0 : aLastCommand = sal_Unicode('H');
2043 : : }
2044 : : }
2045 : : else
2046 : : {
2047 [ + - ]: 12 : if(mbRelative)
2048 : : {
2049 [ - + ]: 12 : if(aLastCommand != sal_Unicode('l'))
2050 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('l'));
2051 : :
2052 [ + - ]: 12 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2053 [ + - ]: 12 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2054 : :
2055 : 12 : aLastCommand = sal_Unicode('l');
2056 : : }
2057 : : else
2058 : : {
2059 [ # # ]: 0 : if(aLastCommand != sal_Unicode('L'))
2060 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('L'));
2061 : :
2062 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
2063 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
2064 : :
2065 : 0 : aLastCommand = sal_Unicode('L');
2066 : : }
2067 : : }
2068 : : }
2069 : : else
2070 : : {
2071 : : // write as start point
2072 [ + - ]: 12 : if(mbRelative)
2073 : : {
2074 : 12 : aNewString += rtl::OUString(static_cast<sal_Unicode>('m'));
2075 : :
2076 [ + - ]: 12 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2077 [ + - ]: 12 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2078 : :
2079 : 12 : aLastCommand = sal_Unicode('l');
2080 : : }
2081 : : else
2082 : : {
2083 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('M'));
2084 : :
2085 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
2086 [ # # ]: 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
2087 : :
2088 : 0 : aLastCommand = sal_Unicode('L');
2089 : : }
2090 : :
2091 : : // remember start written
2092 : 12 : bDidWriteStart = true;
2093 : 12 : nStartX = nX;
2094 : 12 : nStartY = nY;
2095 : : }
2096 : :
2097 : : // remember new last position
2098 : 36 : mnLastX = nX;
2099 : 36 : mnLastY = nY;
2100 : : }
2101 : : }
2102 : :
2103 : : // next point
2104 : 36 : pPointArray++;
2105 : 36 : pFlagArray++;
2106 : : }
2107 : :
2108 : : // close path if closed poly
2109 [ + - ]: 12 : if(bClosed)
2110 : : {
2111 [ + - ]: 12 : if(mbRelative)
2112 : 12 : aNewString += rtl::OUString(static_cast<sal_Unicode>('z'));
2113 : : else
2114 : 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('Z'));
2115 : :
2116 : : // update current point - we're back at the start
2117 [ + - ]: 12 : if( bDidWriteStart )
2118 : : {
2119 : 12 : mnLastX = nStartX;
2120 : 12 : mnLastY = nStartY;
2121 : : }
2122 : : }
2123 : :
2124 : : // append new string
2125 : 12 : msString += aNewString;
2126 : : }
2127 : 12 : }
2128 : :
2129 : 194 : SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew,
2130 : : const SdXMLImExViewBox& rViewBox,
2131 : : const awt::Point& rObjectPos,
2132 : : const awt::Size& rObjectSize,
2133 : : const SvXMLImport& rImport)
2134 : : : msString( rNew ),
2135 : : mrViewBox( rViewBox ),
2136 : : mbIsClosed( false ),
2137 : : mbIsCurve( false ),
2138 : : mbRelative( true ),
2139 : : mnLastX( 0L ),
2140 : : mnLastY( 0L ),
2141 [ + - ]: 194 : maPoly()
2142 : : {
2143 : 194 : bool bWrongPositionAfterZ( false );
2144 : 194 : sal_Int32 nUPD( 0 );
2145 : 194 : sal_Int32 nBuildId( 0 );
2146 [ + - ][ + + ]: 194 : if ( rImport.getBuildIds( nUPD, nBuildId ) &&
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ]
2147 : : ( ( nUPD == 641 ) || ( nUPD == 645 ) || ( nUPD == 680 ) || ( nUPD == 300 ) ||
2148 : : ( nUPD == 310 ) || ( nUPD == 320 ) || ( nUPD == 330 ) || ( nUPD == 340 ) ||
2149 : : ( nUPD == 350 && nBuildId < 202 ) ) )
2150 : : {
2151 : 15 : bWrongPositionAfterZ = true;
2152 : : }
2153 : :
2154 : : // convert string to polygon
2155 [ + - ]: 194 : basegfx::B2DPolyPolygon aPoly;
2156 [ + - ]: 194 : basegfx::tools::importFromSvgD(aPoly,msString,bWrongPositionAfterZ);
2157 : :
2158 [ + - ]: 194 : mbIsCurve = aPoly.areControlPointsUsed();
2159 [ + - ]: 194 : mbIsClosed = aPoly.isClosed();
2160 : :
2161 : : // object size and ViewBox size different?
2162 [ + - ]: 194 : basegfx::B2DHomMatrix aTransform;
2163 : 194 : const bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
2164 [ - + ][ + - ]: 194 : || rObjectSize.Height != mrViewBox.GetHeight());
2165 [ + - ][ - + ]: 194 : const bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
2166 : :
2167 [ - + ]: 194 : if( bTranslate )
2168 : : aTransform.translate(
2169 : 0 : -mrViewBox.GetX(),
2170 [ # # ]: 0 : -mrViewBox.GetY());
2171 [ - + ]: 194 : if( bScale )
2172 : : aTransform.scale(
2173 : 0 : (mrViewBox.GetWidth() ? rObjectSize.Width / mrViewBox.GetWidth() : 0),
2174 [ # # ][ # # ]: 0 : (mrViewBox.GetHeight() ? rObjectSize.Height / mrViewBox.GetHeight() : 0));
[ # # ]
2175 [ + - ]: 194 : aTransform.translate( rObjectPos.X, rObjectPos.Y );
2176 [ + - ]: 194 : aPoly.transform(aTransform);
2177 : :
2178 [ + - ][ + - ]: 194 : basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier(aPoly,maPoly);
[ + - ]
2179 : 194 : }
2180 : :
2181 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|