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