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 : using ::rtl::OUString;
37 : using ::rtl::OUStringBuffer;
38 :
39 : using namespace ::com::sun::star;
40 :
41 : //////////////////////////////////////////////////////////////////////////////
42 : // Defines
43 :
44 : #define BORDER_INTEGERS_ARE_EQUAL (4)
45 :
46 : //////////////////////////////////////////////////////////////////////////////
47 : // Predeclarations
48 :
49 : void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen);
50 0 : void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection)
51 : {
52 0 : const sal_Int32 nLen1(FRound(aVec1.getLength()));
53 0 : const sal_Int32 nLen2(FRound(aVec2.getLength()));
54 0 : aVec1.normalize();
55 0 : aVec2.normalize();
56 0 : aVec1 += aVec2;
57 0 : const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0)));
58 :
59 0 : bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL);
60 0 : bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL);
61 0 : }
62 :
63 :
64 : //////////////////////////////////////////////////////////////////////////////
65 : //////////////////////////////////////////////////////////////////////////////
66 : // parsing help functions for simple chars
67 119 : void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
68 : {
69 357 : while(rPos < nLen
70 119 : && sal_Unicode(' ') == rStr[rPos])
71 0 : rPos++;
72 119 : }
73 :
74 18 : void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
75 : {
76 162 : while(rPos < nLen
77 90 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos]))
78 36 : rPos++;
79 18 : }
80 :
81 416 : void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
82 : {
83 2550 : while(rPos < nLen
84 1312 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos]))
85 406 : rPos++;
86 416 : }
87 :
88 18 : void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
89 : {
90 126 : while(rPos < nLen
91 63 : && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos]))
92 27 : rPos++;
93 18 : }
94 :
95 : //////////////////////////////////////////////////////////////////////////////
96 : //////////////////////////////////////////////////////////////////////////////
97 : // parsing help functions for integer numbers
98 :
99 0 : bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true)
100 : {
101 0 : sal_Unicode aChar(rStr[nPos]);
102 :
103 0 : if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
104 : || (bSignAllowed && sal_Unicode('+') == aChar)
105 : || (bSignAllowed && sal_Unicode('-') == aChar)
106 : )
107 0 : return true;
108 0 : return false;
109 : }
110 :
111 54 : bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos)
112 : {
113 54 : sal_Unicode aChar(rStr[nPos]);
114 :
115 54 : if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
116 : || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
117 : || sal_Unicode('%') == aChar
118 : )
119 36 : return true;
120 18 : return false;
121 : }
122 :
123 0 : void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen)
124 : {
125 0 : bool bSignAllowed(true);
126 :
127 0 : while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed))
128 : {
129 0 : bSignAllowed = false;
130 0 : rPos++;
131 : }
132 0 : }
133 :
134 0 : void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos,
135 : const sal_Int32 nLen)
136 : {
137 0 : Imp_SkipNumber(rStr, rPos, nLen);
138 0 : Imp_SkipSpacesAndCommas(rStr, rPos, nLen);
139 0 : }
140 :
141 0 : void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue)
142 : {
143 0 : OUStringBuffer sStringBuffer;
144 0 : ::sax::Converter::convertNumber(sStringBuffer, nValue);
145 0 : rStr += OUString(sStringBuffer.makeStringAndClear());
146 0 : }
147 :
148 0 : void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue)
149 : {
150 0 : const sal_Int32 aLen(rStr.getLength());
151 0 : if(aLen)
152 0 : if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0)
153 0 : rStr += rtl::OUString(static_cast<sal_Unicode>(' '));
154 0 : Imp_PutNumberChar(rStr, nValue);
155 0 : }
156 :
157 : //////////////////////////////////////////////////////////////////////////////
158 : //////////////////////////////////////////////////////////////////////////////
159 : // parsing help functions for double numbers
160 :
161 94 : void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32)
162 : {
163 94 : sal_Unicode aChar(rStr[rPos]);
164 :
165 94 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
166 0 : aChar = rStr[++rPos];
167 :
168 497 : while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
169 : || sal_Unicode('.') == aChar)
170 : {
171 309 : aChar = rStr[++rPos];
172 : }
173 :
174 94 : if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
175 : {
176 0 : aChar = rStr[++rPos];
177 :
178 0 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
179 0 : aChar = rStr[++rPos];
180 :
181 0 : while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
182 : {
183 0 : aChar = rStr[++rPos];
184 : }
185 : }
186 94 : }
187 :
188 413 : double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen,
189 : const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false)
190 : {
191 413 : sal_Unicode aChar(rStr[rPos]);
192 413 : OUStringBuffer sNumberString;
193 :
194 413 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
195 : {
196 3 : sNumberString.append(rStr[rPos]);
197 3 : aChar = rStr[++rPos];
198 : }
199 :
200 2247 : while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
201 : || sal_Unicode('.') == aChar)
202 : {
203 1421 : sNumberString.append(rStr[rPos]);
204 1421 : aChar = rStr[++rPos];
205 : }
206 :
207 413 : if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
208 : {
209 0 : sNumberString.append(rStr[rPos]);
210 0 : aChar = rStr[++rPos];
211 :
212 0 : if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
213 : {
214 0 : sNumberString.append(rStr[rPos]);
215 0 : aChar = rStr[++rPos];
216 : }
217 :
218 0 : while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
219 : {
220 0 : sNumberString.append(rStr[rPos]);
221 0 : aChar = rStr[++rPos];
222 : }
223 : }
224 :
225 413 : if(bLookForUnits)
226 : {
227 18 : Imp_SkipSpaces(rStr, rPos, nLen);
228 72 : while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos))
229 36 : sNumberString.append(rStr[rPos++]);
230 : }
231 :
232 413 : if(sNumberString.getLength())
233 : {
234 413 : if(bLookForUnits)
235 18 : rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true);
236 : else
237 : {
238 : ::sax::Converter::convertDouble(fRetval,
239 395 : sNumberString.makeStringAndClear());
240 : }
241 : }
242 :
243 413 : return fRetval;
244 : }
245 :
246 0 : void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue,
247 : bool bConvertUnits = false)
248 : {
249 0 : OUStringBuffer sStringBuffer;
250 :
251 0 : if(bConvertUnits)
252 0 : rConv.convertDouble(sStringBuffer, fValue, true);
253 : else
254 : {
255 0 : ::sax::Converter::convertDouble(sStringBuffer, fValue);
256 : }
257 :
258 0 : rStr += OUString(sStringBuffer.makeStringAndClear());
259 0 : }
260 :
261 : //////////////////////////////////////////////////////////////////////////////
262 : //////////////////////////////////////////////////////////////////////////////
263 : // base class of all 2D transform objects
264 :
265 : struct ImpSdXMLExpTransObj2DBase
266 : {
267 : sal_uInt16 mnType;
268 18 : ImpSdXMLExpTransObj2DBase(sal_uInt16 nType)
269 18 : : mnType(nType) {}
270 : };
271 :
272 : //////////////////////////////////////////////////////////////////////////////
273 : // possible object types for 2D
274 :
275 : #define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000
276 : #define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001
277 : #define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002
278 : #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003
279 : #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004
280 : #define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005
281 :
282 : //////////////////////////////////////////////////////////////////////////////
283 : // classes of objects, different sizes
284 :
285 : struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase
286 : {
287 : double mfRotate;
288 9 : ImpSdXMLExpTransObj2DRotate(double fVal)
289 9 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {}
290 : };
291 0 : struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase
292 : {
293 : ::basegfx::B2DTuple maScale;
294 0 : ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew)
295 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {}
296 : };
297 9 : struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase
298 : {
299 : ::basegfx::B2DTuple maTranslate;
300 9 : ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew)
301 9 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {}
302 : };
303 : struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase
304 : {
305 : double mfSkewX;
306 0 : ImpSdXMLExpTransObj2DSkewX(double fVal)
307 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {}
308 : };
309 : struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase
310 : {
311 : double mfSkewY;
312 0 : ImpSdXMLExpTransObj2DSkewY(double fVal)
313 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {}
314 : };
315 0 : struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase
316 : {
317 : ::basegfx::B2DHomMatrix maMatrix;
318 0 : ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew)
319 0 : : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {}
320 : };
321 :
322 : //////////////////////////////////////////////////////////////////////////////
323 : //////////////////////////////////////////////////////////////////////////////
324 : // delete all entries in list
325 :
326 179 : void SdXMLImExTransform2D::EmptyList()
327 : {
328 179 : const sal_uInt32 nCount = maList.size();
329 197 : for(sal_uInt32 a(0L); a < nCount; a++)
330 : {
331 18 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
332 :
333 18 : switch(pObj->mnType)
334 : {
335 : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
336 : {
337 9 : delete (ImpSdXMLExpTransObj2DRotate*)pObj;
338 9 : break;
339 : }
340 : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
341 : {
342 0 : delete (ImpSdXMLExpTransObj2DScale*)pObj;
343 0 : break;
344 : }
345 : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
346 : {
347 9 : delete (ImpSdXMLExpTransObj2DTranslate*)pObj;
348 9 : break;
349 : }
350 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
351 : {
352 0 : delete (ImpSdXMLExpTransObj2DSkewX*)pObj;
353 0 : break;
354 : }
355 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
356 : {
357 0 : delete (ImpSdXMLExpTransObj2DSkewY*)pObj;
358 0 : break;
359 : }
360 : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
361 : {
362 0 : delete (ImpSdXMLExpTransObj2DMatrix*)pObj;
363 0 : break;
364 : }
365 : default :
366 : {
367 : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
368 0 : break;
369 : }
370 : }
371 : }
372 :
373 179 : maList.clear();
374 179 : }
375 :
376 : //////////////////////////////////////////////////////////////////////////////
377 : // add members
378 :
379 0 : void SdXMLImExTransform2D::AddRotate(double fNew)
380 : {
381 0 : if(fNew != 0.0)
382 0 : maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew));
383 0 : }
384 :
385 0 : void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew)
386 : {
387 0 : if(!rNew.equalZero())
388 0 : maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew));
389 0 : }
390 :
391 0 : void SdXMLImExTransform2D::AddSkewX(double fNew)
392 : {
393 0 : if(fNew != 0.0)
394 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew));
395 0 : }
396 :
397 : //////////////////////////////////////////////////////////////////////////////
398 : // gen string for export
399 0 : const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv)
400 : {
401 0 : OUString aNewString;
402 0 : OUString aClosingBrace(sal_Unicode(')'));
403 0 : OUString aEmptySpace(sal_Unicode(' '));
404 :
405 0 : const sal_uInt32 nCount = maList.size();
406 0 : for(sal_uInt32 a(0L); a < nCount; a++)
407 : {
408 0 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
409 0 : switch(pObj->mnType)
410 : {
411 : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
412 : {
413 0 : aNewString += OUString( "rotate (" );
414 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate);
415 0 : aNewString += aClosingBrace;
416 0 : break;
417 : }
418 : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
419 : {
420 0 : aNewString += OUString( "scale (" );
421 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX());
422 0 : aNewString += aEmptySpace;
423 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY());
424 0 : aNewString += aClosingBrace;
425 0 : break;
426 : }
427 : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
428 : {
429 0 : aNewString += OUString( "translate (" );
430 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true);
431 0 : aNewString += aEmptySpace;
432 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true);
433 0 : aNewString += aClosingBrace;
434 0 : break;
435 : }
436 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
437 : {
438 0 : aNewString += OUString( "skewX (" );
439 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX);
440 0 : aNewString += aClosingBrace;
441 0 : break;
442 : }
443 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
444 : {
445 0 : aNewString += OUString( "skewY (" );
446 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY);
447 0 : aNewString += aClosingBrace;
448 0 : break;
449 : }
450 : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
451 : {
452 0 : aNewString += OUString( "matrix (" );
453 :
454 : // a
455 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0));
456 0 : aNewString += aEmptySpace;
457 :
458 : // b
459 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0));
460 0 : aNewString += aEmptySpace;
461 :
462 : // c
463 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1));
464 0 : aNewString += aEmptySpace;
465 :
466 : // d
467 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1));
468 0 : aNewString += aEmptySpace;
469 :
470 : // e
471 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true);
472 0 : aNewString += aEmptySpace;
473 :
474 : // f
475 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true);
476 :
477 0 : aNewString += aClosingBrace;
478 0 : break;
479 : }
480 : default :
481 : {
482 : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
483 0 : break;
484 : }
485 : }
486 :
487 : // if not the last entry, add one space to next tag
488 0 : if(a + 1UL != maList.size())
489 : {
490 0 : aNewString += aEmptySpace;
491 : }
492 : }
493 :
494 : // fill string form OUString
495 0 : msString = aNewString;
496 :
497 0 : return msString;
498 : }
499 :
500 : //////////////////////////////////////////////////////////////////////////////
501 : // sets new string, parses it and generates entries
502 9 : void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
503 : {
504 9 : msString = rNew;
505 9 : EmptyList();
506 :
507 9 : if(!msString.isEmpty())
508 : {
509 9 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
510 9 : const sal_Int32 nLen(aStr.getLength());
511 :
512 9 : const OUString aString_rotate( "rotate" );
513 9 : const OUString aString_scale( "scale" );
514 9 : const OUString aString_translate( "translate" );
515 9 : const OUString aString_skewX( "skewX" );
516 9 : const OUString aString_skewY( "skewY" );
517 9 : const OUString aString_matrix( "matrix" );
518 :
519 9 : sal_Int32 nPos(0);
520 :
521 36 : while(nPos < nLen)
522 : {
523 : // skip spaces
524 18 : Imp_SkipSpaces(aStr, nPos, nLen);
525 :
526 : // look for tag
527 18 : if(nPos < nLen)
528 : {
529 18 : if(nPos == aStr.indexOf(aString_rotate, nPos))
530 : {
531 9 : double fValue(0.0);
532 9 : nPos += 6;
533 9 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
534 9 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
535 9 : if(fValue != 0.0)
536 9 : maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue));
537 :
538 9 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
539 : }
540 9 : else if(nPos == aStr.indexOf(aString_scale, nPos))
541 : {
542 0 : ::basegfx::B2DTuple aValue(1.0, 1.0);
543 0 : nPos += 5;
544 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
545 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
546 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
547 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
548 :
549 0 : if(aValue.getX() != 1.0 || aValue.getY() != 1.0)
550 0 : maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue));
551 :
552 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
553 : }
554 9 : else if(nPos == aStr.indexOf(aString_translate, nPos))
555 : {
556 9 : ::basegfx::B2DTuple aValue;
557 9 : nPos += 9;
558 9 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
559 9 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
560 9 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
561 9 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
562 :
563 9 : if(!aValue.equalZero())
564 9 : maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue));
565 :
566 9 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
567 : }
568 0 : else if(nPos == aStr.indexOf(aString_skewX, nPos))
569 : {
570 0 : double fValue(0.0);
571 0 : nPos += 5;
572 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
573 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
574 0 : if(fValue != 0.0)
575 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue));
576 :
577 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
578 : }
579 0 : else if(nPos == aStr.indexOf(aString_skewY, nPos))
580 : {
581 0 : double fValue(0.0);
582 0 : nPos += 5;
583 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
584 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
585 0 : if(fValue != 0.0)
586 0 : maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue));
587 :
588 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
589 : }
590 0 : else if(nPos == aStr.indexOf(aString_matrix, nPos))
591 : {
592 0 : ::basegfx::B2DHomMatrix aValue;
593 :
594 0 : nPos += 6;
595 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
596 :
597 : // a
598 0 : aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
599 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
600 :
601 : // b
602 0 : aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
603 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
604 :
605 : // c
606 0 : aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
607 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
608 :
609 : // d
610 0 : aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
611 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
612 :
613 : // e
614 0 : aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true));
615 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
616 :
617 : // f
618 0 : aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true));
619 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
620 :
621 0 : if(!aValue.isIdentity())
622 0 : maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue));
623 :
624 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
625 : }
626 : else
627 : {
628 0 : nPos++;
629 : }
630 : }
631 9 : }
632 : }
633 9 : }
634 :
635 9 : void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans)
636 : {
637 9 : rFullTrans.identity();
638 :
639 9 : const sal_uInt32 nCount = maList.size();
640 27 : for(sal_uInt32 a(0L); a < nCount; a++)
641 : {
642 18 : ImpSdXMLExpTransObj2DBase* pObj = maList[a];
643 18 : switch(pObj->mnType)
644 : {
645 : case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE :
646 : {
647 : // #i78696#
648 : // mfRotate is mathematically wrong oriented since we export/import the angle
649 : // values mirrored. This error is fixed in the API, but not yet in the FileFormat.
650 : // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next
651 : // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary
652 : // to mirror the value here
653 9 : rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0);
654 9 : break;
655 : }
656 : case IMP_SDXMLEXP_TRANSOBJ2D_SCALE :
657 : {
658 0 : const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale;
659 0 : rFullTrans.scale(rScale.getX(), rScale.getY());
660 0 : break;
661 : }
662 : case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE :
663 : {
664 9 : const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate;
665 9 : rFullTrans.translate(rTranslate.getX(), rTranslate.getY());
666 9 : break;
667 : }
668 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX :
669 : {
670 0 : rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX));
671 0 : break;
672 : }
673 : case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY :
674 : {
675 0 : rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY));
676 0 : break;
677 : }
678 : case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX :
679 : {
680 0 : rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix;
681 0 : break;
682 : }
683 : default :
684 : {
685 : OSL_FAIL("SdXMLImExTransform2D: impossible entry!");
686 0 : break;
687 : }
688 : }
689 : }
690 9 : }
691 :
692 : //////////////////////////////////////////////////////////////////////////////
693 : //////////////////////////////////////////////////////////////////////////////
694 : // base class of all 3D transform objects
695 :
696 : struct ImpSdXMLExpTransObj3DBase
697 : {
698 : sal_uInt16 mnType;
699 0 : ImpSdXMLExpTransObj3DBase(sal_uInt16 nType)
700 0 : : mnType(nType) {}
701 : };
702 :
703 : //////////////////////////////////////////////////////////////////////////////
704 : // possible object types for 3D
705 :
706 : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000
707 : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001
708 : #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002
709 : #define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003
710 : #define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004
711 : #define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005
712 :
713 : //////////////////////////////////////////////////////////////////////////////
714 : // classes of objects, different sizes
715 :
716 : struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase
717 : {
718 : double mfRotateX;
719 0 : ImpSdXMLExpTransObj3DRotateX(double fVal)
720 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {}
721 : };
722 : struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase
723 : {
724 : double mfRotateY;
725 0 : ImpSdXMLExpTransObj3DRotateY(double fVal)
726 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {}
727 : };
728 : struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase
729 : {
730 : double mfRotateZ;
731 0 : ImpSdXMLExpTransObj3DRotateZ(double fVal)
732 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {}
733 : };
734 0 : struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase
735 : {
736 : ::basegfx::B3DTuple maScale;
737 0 : ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew)
738 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {}
739 : };
740 0 : struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase
741 : {
742 : ::basegfx::B3DTuple maTranslate;
743 0 : ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew)
744 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {}
745 : };
746 0 : struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase
747 : {
748 : ::basegfx::B3DHomMatrix maMatrix;
749 0 : ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew)
750 0 : : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {}
751 : };
752 :
753 : //////////////////////////////////////////////////////////////////////////////
754 : //////////////////////////////////////////////////////////////////////////////
755 : // delete all entries in list
756 :
757 0 : void SdXMLImExTransform3D::EmptyList()
758 : {
759 0 : const sal_uInt32 nCount = maList.size();
760 0 : for(sal_uInt32 a(0L); a < nCount; a++)
761 : {
762 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
763 :
764 0 : switch(pObj->mnType)
765 : {
766 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
767 : {
768 0 : delete (ImpSdXMLExpTransObj3DRotateX*)pObj;
769 0 : break;
770 : }
771 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
772 : {
773 0 : delete (ImpSdXMLExpTransObj3DRotateY*)pObj;
774 0 : break;
775 : }
776 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
777 : {
778 0 : delete (ImpSdXMLExpTransObj3DRotateZ*)pObj;
779 0 : break;
780 : }
781 : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
782 : {
783 0 : delete (ImpSdXMLExpTransObj3DScale*)pObj;
784 0 : break;
785 : }
786 : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
787 : {
788 0 : delete (ImpSdXMLExpTransObj3DTranslate*)pObj;
789 0 : break;
790 : }
791 : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
792 : {
793 0 : delete (ImpSdXMLExpTransObj3DMatrix*)pObj;
794 0 : break;
795 : }
796 : default :
797 : {
798 : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
799 0 : break;
800 : }
801 : }
802 : }
803 :
804 0 : maList.clear();
805 0 : }
806 :
807 : //////////////////////////////////////////////////////////////////////////////
808 : // add members
809 :
810 0 : void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew)
811 : {
812 0 : if(!rNew.isIdentity())
813 0 : maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew));
814 0 : }
815 :
816 0 : void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat)
817 : {
818 0 : ::basegfx::B3DHomMatrix aExportMatrix;
819 :
820 0 : aExportMatrix.set(0, 0, xHomMat.Line1.Column1);
821 0 : aExportMatrix.set(0, 1, xHomMat.Line1.Column2);
822 0 : aExportMatrix.set(0, 2, xHomMat.Line1.Column3);
823 0 : aExportMatrix.set(0, 3, xHomMat.Line1.Column4);
824 0 : aExportMatrix.set(1, 0, xHomMat.Line2.Column1);
825 0 : aExportMatrix.set(1, 1, xHomMat.Line2.Column2);
826 0 : aExportMatrix.set(1, 2, xHomMat.Line2.Column3);
827 0 : aExportMatrix.set(1, 3, xHomMat.Line2.Column4);
828 0 : aExportMatrix.set(2, 0, xHomMat.Line3.Column1);
829 0 : aExportMatrix.set(2, 1, xHomMat.Line3.Column2);
830 0 : aExportMatrix.set(2, 2, xHomMat.Line3.Column3);
831 0 : aExportMatrix.set(2, 3, xHomMat.Line3.Column4);
832 :
833 0 : AddMatrix(aExportMatrix);
834 0 : }
835 :
836 : //////////////////////////////////////////////////////////////////////////////
837 : // gen string for export
838 0 : const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv)
839 : {
840 0 : OUString aNewString;
841 0 : OUString aClosingBrace(sal_Unicode(')'));
842 0 : OUString aEmptySpace(sal_Unicode(' '));
843 :
844 0 : const sal_uInt32 nCount = maList.size();
845 0 : for(sal_uInt32 a(0L); a < nCount; a++)
846 : {
847 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
848 0 : switch(pObj->mnType)
849 : {
850 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
851 : {
852 0 : aNewString += OUString( "rotatex (" );
853 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX);
854 0 : aNewString += aClosingBrace;
855 0 : break;
856 : }
857 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
858 : {
859 0 : aNewString += OUString( "rotatey (" );
860 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY);
861 0 : aNewString += aClosingBrace;
862 0 : break;
863 : }
864 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
865 : {
866 0 : aNewString += OUString( "rotatez (" );
867 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
868 0 : aNewString += aClosingBrace;
869 0 : break;
870 : }
871 : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
872 : {
873 0 : aNewString += OUString( "scale (" );
874 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX());
875 0 : aNewString += aEmptySpace;
876 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY());
877 0 : aNewString += aEmptySpace;
878 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ());
879 0 : aNewString += aClosingBrace;
880 0 : break;
881 : }
882 : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
883 : {
884 0 : aNewString += OUString( "translate (" );
885 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true);
886 0 : aNewString += aEmptySpace;
887 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true);
888 0 : aNewString += aEmptySpace;
889 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true);
890 0 : aNewString += aClosingBrace;
891 0 : break;
892 : }
893 : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
894 : {
895 0 : aNewString += OUString( "matrix (" );
896 :
897 : // a
898 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0));
899 0 : aNewString += aEmptySpace;
900 :
901 : // b
902 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0));
903 0 : aNewString += aEmptySpace;
904 :
905 : // c
906 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0));
907 0 : aNewString += aEmptySpace;
908 :
909 : // d
910 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1));
911 0 : aNewString += aEmptySpace;
912 :
913 : // e
914 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1));
915 0 : aNewString += aEmptySpace;
916 :
917 : // f
918 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1));
919 0 : aNewString += aEmptySpace;
920 :
921 : // g
922 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2));
923 0 : aNewString += aEmptySpace;
924 :
925 : // h
926 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2));
927 0 : aNewString += aEmptySpace;
928 :
929 : // i
930 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2));
931 0 : aNewString += aEmptySpace;
932 :
933 : // j
934 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true);
935 0 : aNewString += aEmptySpace;
936 :
937 : // k
938 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true);
939 0 : aNewString += aEmptySpace;
940 :
941 : // l
942 0 : Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true);
943 :
944 0 : aNewString += aClosingBrace;
945 0 : break;
946 : }
947 : default :
948 : {
949 : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
950 0 : break;
951 : }
952 : }
953 :
954 : // if not the last entry, add one space to next tag
955 0 : if(a + 1UL != maList.size())
956 : {
957 0 : aNewString += aEmptySpace;
958 : }
959 : }
960 :
961 : // fill string form OUString
962 0 : msString = aNewString;
963 :
964 0 : return msString;
965 : }
966 :
967 : //////////////////////////////////////////////////////////////////////////////
968 : // for Import: constructor with string, parses it and generates entries
969 0 : SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv)
970 : {
971 0 : SetString(rNew, rConv);
972 0 : }
973 :
974 : //////////////////////////////////////////////////////////////////////////////
975 : // sets new string, parses it and generates entries
976 0 : void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv)
977 : {
978 0 : msString = rNew;
979 0 : EmptyList();
980 :
981 0 : if(!msString.isEmpty())
982 : {
983 0 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
984 0 : const sal_Int32 nLen(aStr.getLength());
985 :
986 0 : const OUString aString_rotatex( "rotatex" );
987 0 : const OUString aString_rotatey( "rotatey" );
988 0 : const OUString aString_rotatez( "rotatez" );
989 0 : const OUString aString_scale( "scale" );
990 0 : const OUString aString_translate( "translate" );
991 0 : const OUString aString_matrix( "matrix" );
992 :
993 0 : sal_Int32 nPos(0);
994 :
995 0 : while(nPos < nLen)
996 : {
997 : // skip spaces
998 0 : Imp_SkipSpaces(aStr, nPos, nLen);
999 :
1000 : // look for tag
1001 0 : if(nPos < nLen)
1002 : {
1003 0 : if(nPos == aStr.indexOf(aString_rotatex, nPos))
1004 : {
1005 0 : double fValue(0.0);
1006 :
1007 0 : nPos += 7;
1008 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1009 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1010 0 : if(fValue != 0.0)
1011 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue));
1012 :
1013 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1014 : }
1015 0 : else if(nPos == aStr.indexOf(aString_rotatey, nPos))
1016 : {
1017 0 : double fValue(0.0);
1018 :
1019 0 : nPos += 7;
1020 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1021 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1022 0 : if(fValue != 0.0)
1023 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue));
1024 :
1025 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1026 : }
1027 0 : else if(nPos == aStr.indexOf(aString_rotatez, nPos))
1028 : {
1029 0 : double fValue(0.0);
1030 :
1031 0 : nPos += 7;
1032 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1033 0 : fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue);
1034 0 : if(fValue != 0.0)
1035 0 : maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue));
1036 :
1037 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1038 : }
1039 0 : else if(nPos == aStr.indexOf(aString_scale, nPos))
1040 : {
1041 0 : ::basegfx::B3DTuple aValue(1.0, 1.0, 1.0);
1042 :
1043 0 : nPos += 5;
1044 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1045 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX()));
1046 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1047 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY()));
1048 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1049 0 : aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ()));
1050 :
1051 0 : if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ())
1052 0 : maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue));
1053 :
1054 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1055 : }
1056 0 : else if(nPos == aStr.indexOf(aString_translate, nPos))
1057 : {
1058 0 : ::basegfx::B3DTuple aValue;
1059 :
1060 0 : nPos += 9;
1061 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1062 0 : aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true));
1063 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1064 0 : aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true));
1065 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1066 0 : aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true));
1067 :
1068 0 : if(!aValue.equalZero())
1069 0 : maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue));
1070 :
1071 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1072 : }
1073 0 : else if(nPos == aStr.indexOf(aString_matrix, nPos))
1074 : {
1075 0 : ::basegfx::B3DHomMatrix aValue;
1076 :
1077 0 : nPos += 6;
1078 0 : Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen);
1079 :
1080 : // a
1081 0 : aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0)));
1082 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1083 :
1084 : // b
1085 0 : aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0)));
1086 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1087 :
1088 : // c
1089 0 : aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0)));
1090 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1091 :
1092 : // d
1093 0 : aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1)));
1094 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1095 :
1096 : // e
1097 0 : aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1)));
1098 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1099 :
1100 : // f
1101 0 : aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1)));
1102 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1103 :
1104 : // g
1105 0 : aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2)));
1106 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1107 :
1108 : // h
1109 0 : aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2)));
1110 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1111 :
1112 : // i
1113 0 : aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2)));
1114 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1115 :
1116 : // j
1117 0 : aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true));
1118 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1119 :
1120 : // k
1121 0 : aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true));
1122 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1123 :
1124 : // l
1125 0 : aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true));
1126 0 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1127 :
1128 0 : if(!aValue.isIdentity())
1129 0 : maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue));
1130 :
1131 0 : Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen);
1132 : }
1133 : else
1134 : {
1135 0 : nPos++;
1136 : }
1137 : }
1138 0 : }
1139 : }
1140 0 : }
1141 :
1142 0 : bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat)
1143 : {
1144 0 : ::basegfx::B3DHomMatrix aFullTransform;
1145 0 : GetFullTransform(aFullTransform);
1146 :
1147 0 : if(!aFullTransform.isIdentity())
1148 : {
1149 0 : xHomMat.Line1.Column1 = aFullTransform.get(0, 0);
1150 0 : xHomMat.Line1.Column2 = aFullTransform.get(0, 1);
1151 0 : xHomMat.Line1.Column3 = aFullTransform.get(0, 2);
1152 0 : xHomMat.Line1.Column4 = aFullTransform.get(0, 3);
1153 :
1154 0 : xHomMat.Line2.Column1 = aFullTransform.get(1, 0);
1155 0 : xHomMat.Line2.Column2 = aFullTransform.get(1, 1);
1156 0 : xHomMat.Line2.Column3 = aFullTransform.get(1, 2);
1157 0 : xHomMat.Line2.Column4 = aFullTransform.get(1, 3);
1158 :
1159 0 : xHomMat.Line3.Column1 = aFullTransform.get(2, 0);
1160 0 : xHomMat.Line3.Column2 = aFullTransform.get(2, 1);
1161 0 : xHomMat.Line3.Column3 = aFullTransform.get(2, 2);
1162 0 : xHomMat.Line3.Column4 = aFullTransform.get(2, 3);
1163 :
1164 0 : xHomMat.Line4.Column1 = aFullTransform.get(3, 0);
1165 0 : xHomMat.Line4.Column2 = aFullTransform.get(3, 1);
1166 0 : xHomMat.Line4.Column3 = aFullTransform.get(3, 2);
1167 0 : xHomMat.Line4.Column4 = aFullTransform.get(3, 3);
1168 :
1169 0 : return true;
1170 : }
1171 :
1172 0 : return false;
1173 : }
1174 :
1175 0 : void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans)
1176 : {
1177 0 : rFullTrans.identity();
1178 :
1179 0 : const sal_uInt32 nCount = maList.size();
1180 0 : for(sal_uInt32 a(0L); a < nCount; a++)
1181 : {
1182 0 : ImpSdXMLExpTransObj3DBase* pObj = maList[a];
1183 0 : switch(pObj->mnType)
1184 : {
1185 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X :
1186 : {
1187 0 : rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0);
1188 0 : break;
1189 : }
1190 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y :
1191 : {
1192 0 : rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0);
1193 0 : break;
1194 : }
1195 : case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z :
1196 : {
1197 0 : rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ);
1198 0 : break;
1199 : }
1200 : case IMP_SDXMLEXP_TRANSOBJ3D_SCALE :
1201 : {
1202 0 : const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale;
1203 0 : rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ());
1204 0 : break;
1205 : }
1206 : case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE :
1207 : {
1208 0 : const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate;
1209 0 : rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ());
1210 0 : break;
1211 : }
1212 : case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX :
1213 : {
1214 0 : rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix;
1215 0 : break;
1216 : }
1217 : default :
1218 : {
1219 : OSL_FAIL("SdXMLImExTransform3D: impossible entry!");
1220 0 : break;
1221 : }
1222 : }
1223 : }
1224 0 : }
1225 :
1226 : //////////////////////////////////////////////////////////////////////////////
1227 : //////////////////////////////////////////////////////////////////////////////
1228 :
1229 0 : SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH)
1230 : : mnX( nX ),
1231 : mnY( nY ),
1232 : mnW( nW ),
1233 0 : mnH( nH )
1234 : {
1235 0 : }
1236 :
1237 : // #100617# Asked vincent hardy: svg:viewBox values may be double precision.
1238 73 : SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv)
1239 : : msString(rNew),
1240 : mnX( 0L ),
1241 : mnY( 0L ),
1242 : mnW( 1000L ),
1243 73 : mnH( 1000L )
1244 : {
1245 73 : if(!msString.isEmpty())
1246 : {
1247 73 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1248 73 : const sal_Int32 nLen(aStr.getLength());
1249 73 : sal_Int32 nPos(0);
1250 :
1251 : // skip starting spaces
1252 73 : Imp_SkipSpaces(aStr, nPos, nLen);
1253 :
1254 : // get mX, #100617# be prepared for doubles
1255 73 : mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX));
1256 :
1257 : // skip spaces and commas
1258 73 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1259 :
1260 : // get mY, #100617# be prepared for doubles
1261 73 : mnY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnY));
1262 :
1263 : // skip spaces and commas
1264 73 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1265 :
1266 : // get mW, #100617# be prepared for doubles
1267 73 : mnW = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnW));
1268 :
1269 : // skip spaces and commas
1270 73 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1271 :
1272 : // get mH, #100617# be prepared for doubles
1273 73 : mnH = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnH));
1274 : }
1275 73 : }
1276 :
1277 0 : const OUString& SdXMLImExViewBox::GetExportString()
1278 : {
1279 0 : OUString aNewString;
1280 0 : OUString aEmptySpace(sal_Unicode(' '));
1281 :
1282 0 : Imp_PutNumberChar(aNewString, mnX);
1283 0 : aNewString += aEmptySpace;
1284 :
1285 0 : Imp_PutNumberChar(aNewString, mnY);
1286 0 : aNewString += aEmptySpace;
1287 :
1288 0 : Imp_PutNumberChar(aNewString, mnW);
1289 0 : aNewString += aEmptySpace;
1290 :
1291 0 : Imp_PutNumberChar(aNewString, mnH);
1292 :
1293 : // set new string
1294 0 : msString = aNewString;
1295 :
1296 0 : return msString;
1297 : }
1298 :
1299 : //////////////////////////////////////////////////////////////////////////////
1300 : //////////////////////////////////////////////////////////////////////////////
1301 :
1302 0 : SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints,
1303 : const SdXMLImExViewBox& rViewBox,
1304 : const awt::Point& rObjectPos,
1305 : const awt::Size& rObjectSize,
1306 : // #96328#
1307 : const bool bClosed)
1308 0 : : maPoly( 0L )
1309 : {
1310 : DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)");
1311 :
1312 : // add polygon to string
1313 0 : sal_Int32 nCnt(pPoints->getLength());
1314 :
1315 : // #104076# Convert to string only when at last one point included
1316 0 : if(nCnt > 0)
1317 : {
1318 0 : OUString aNewString;
1319 0 : awt::Point* pArray = pPoints->getArray();
1320 :
1321 : // last point same? Ignore it.
1322 : // #96328# ...but only when polygon is CLOSED
1323 0 : if(bClosed && (pArray->X == (pArray + (nCnt - 1))->X) && (pArray->Y == (pArray + (nCnt - 1))->Y))
1324 0 : nCnt--;
1325 :
1326 : // object size and ViewBox size different?
1327 0 : bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1328 0 : || rObjectSize.Height != rViewBox.GetHeight());
1329 0 : bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1330 :
1331 0 : for(sal_Int32 a(0L); a < nCnt; a++)
1332 : {
1333 : // prepare coordinates
1334 0 : sal_Int32 nX( pArray->X - rObjectPos.X );
1335 0 : sal_Int32 nY( pArray->Y - rObjectPos.Y );
1336 :
1337 0 : if(bScale && rObjectSize.Width && rObjectSize.Height)
1338 : {
1339 0 : nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width;
1340 0 : nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height;
1341 : }
1342 :
1343 0 : if(bTranslate)
1344 : {
1345 0 : nX += rViewBox.GetX();
1346 0 : nY += rViewBox.GetY();
1347 : }
1348 :
1349 : // X and comma
1350 0 : Imp_PutNumberChar(aNewString, nX);
1351 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>(','));
1352 :
1353 : // Y and space (not for last)
1354 0 : Imp_PutNumberChar(aNewString, nY);
1355 0 : if(a + 1 != nCnt)
1356 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>(' '));
1357 :
1358 : // next point
1359 0 : pArray++;
1360 : }
1361 :
1362 : // set new string
1363 0 : msString = aNewString;
1364 : }
1365 0 : }
1366 :
1367 : // #100617# svg:polyline or svg:polygon values may be double precision.
1368 5 : SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString& rNew,
1369 : const SdXMLImExViewBox& rViewBox,
1370 : const awt::Point& rObjectPos,
1371 : const awt::Size& rObjectSize,
1372 : const SvXMLUnitConverter& rConv)
1373 : : msString( rNew ),
1374 5 : maPoly( 0L )
1375 : {
1376 : // convert string to polygon
1377 5 : const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength());
1378 5 : const sal_Int32 nLen(aStr.getLength());
1379 5 : sal_Int32 nPos(0);
1380 5 : sal_Int32 nNumPoints(0L);
1381 :
1382 : // skip starting spaces
1383 5 : Imp_SkipSpaces(aStr, nPos, nLen);
1384 :
1385 : // count points in first loop
1386 57 : while(nPos < nLen)
1387 : {
1388 : // skip number, #100617# be prepared for doubles
1389 47 : Imp_SkipDouble(aStr, nPos, nLen);
1390 :
1391 : // skip spaces and commas
1392 47 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1393 :
1394 : // skip number, #100617# be prepared for doubles
1395 47 : Imp_SkipDouble(aStr, nPos, nLen);
1396 :
1397 : // skip spaces and commas
1398 47 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1399 :
1400 : // one more point
1401 47 : nNumPoints++;
1402 : }
1403 :
1404 : // second loop
1405 5 : if(nNumPoints)
1406 : {
1407 5 : nPos = 0;
1408 5 : maPoly.realloc(1);
1409 5 : drawing::PointSequence* pOuterSequence = maPoly.getArray();
1410 5 : pOuterSequence->realloc(nNumPoints);
1411 5 : awt::Point* pInnerSequence = pOuterSequence->getArray();
1412 :
1413 : // object size and ViewBox size different?
1414 5 : bool bScale(rObjectSize.Width != rViewBox.GetWidth()
1415 10 : || rObjectSize.Height != rViewBox.GetHeight());
1416 5 : bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L);
1417 :
1418 : // skip starting spaces
1419 5 : Imp_SkipSpaces(aStr, nPos, nLen);
1420 :
1421 57 : while(nPos < nLen)
1422 : {
1423 : // prepare new parameter pair
1424 47 : sal_Int32 nX(0L);
1425 47 : sal_Int32 nY(0L);
1426 :
1427 : // get mX, #100617# be prepared for doubles
1428 47 : nX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nX));
1429 :
1430 : // skip spaces and commas
1431 47 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1432 :
1433 : // get mY, #100617# be prepared for doubles
1434 47 : nY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nY));
1435 :
1436 : // skip spaces and commas
1437 47 : Imp_SkipSpacesAndCommas(aStr, nPos, nLen);
1438 :
1439 : // prepare parameters
1440 47 : if(bTranslate)
1441 : {
1442 0 : nX -= rViewBox.GetX();
1443 0 : nY -= rViewBox.GetY();
1444 : }
1445 :
1446 47 : if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight() )
1447 : {
1448 0 : nX = (nX * rObjectSize.Width) / rViewBox.GetWidth();
1449 0 : nY = (nY * rObjectSize.Height) / rViewBox.GetHeight();
1450 : }
1451 :
1452 47 : nX += rObjectPos.X;
1453 47 : nY += rObjectPos.Y;
1454 :
1455 : // add new point
1456 47 : *pInnerSequence = awt::Point( nX, nY );
1457 47 : pInnerSequence++;
1458 : }
1459 5 : }
1460 5 : }
1461 :
1462 : //////////////////////////////////////////////////////////////////////////////
1463 : //////////////////////////////////////////////////////////////////////////////
1464 :
1465 0 : SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox,
1466 : const SvXMLExport& rExport)
1467 : : mrViewBox( rViewBox ),
1468 : mbIsClosed( false ),
1469 : mbIsCurve( false ),
1470 : // fdo#47406 - handle writing svg:d path slightly different for
1471 : // old odf versions and ODF1.2 compat mode - since ~all the legacy
1472 : // ODF ecosystem interprets relative svg:d paths incorrectly,
1473 : // write out absolute paths in those cases.
1474 0 : mbRelative( rExport.getDefaultVersion() >= SvtSaveOptions::ODFVER_012 &&
1475 0 : rExport.getDefaultVersion() != SvtSaveOptions::ODFVER_012_EXT_COMPAT ),
1476 : mnLastX( 0L ),
1477 : mnLastY( 0L ),
1478 0 : maPoly()
1479 : {
1480 0 : }
1481 :
1482 0 : void Imp_GetPrevPos(awt::Point*& pPrevPos1,
1483 : drawing::PolygonFlags& aPrevFlag1,
1484 : const bool bClosed, awt::Point* pPoints,
1485 : drawing::PolygonFlags* pFlags, const sal_Int32 nPos,
1486 : const sal_Int32 nCnt, const sal_Int32 nAdd)
1487 : {
1488 0 : if(bClosed)
1489 : {
1490 0 : pPrevPos1 = pPoints + ((nPos + nCnt - nAdd) % nCnt);
1491 0 : aPrevFlag1 = *(pFlags + ((nPos + nCnt - nAdd) % nCnt));
1492 : }
1493 0 : else if(nPos > (nAdd - 1))
1494 : {
1495 0 : pPrevPos1 = pPoints + (nPos - nAdd);
1496 0 : aPrevFlag1 = *(pFlags + (nPos - nAdd));
1497 : }
1498 : else
1499 0 : pPrevPos1 = 0L;
1500 0 : }
1501 :
1502 0 : void Imp_PrepareCoorExport(sal_Int32& nX, sal_Int32& nY,
1503 : const awt::Point* pPointArray, const awt::Point& rObjectPos,
1504 : const awt::Size& rObjectSize, const SdXMLImExViewBox& mrViewBox,
1505 : const bool bScale, const bool bTranslate)
1506 : {
1507 0 : nX = pPointArray->X - rObjectPos.X;
1508 0 : nY = pPointArray->Y - rObjectPos.Y;
1509 :
1510 0 : if(bScale && rObjectSize.Width && rObjectSize.Height )
1511 : {
1512 0 : nX = (nX * mrViewBox.GetWidth()) / rObjectSize.Width;
1513 0 : nY = (nY * mrViewBox.GetHeight()) / rObjectSize.Height;
1514 : }
1515 :
1516 0 : if(bTranslate)
1517 : {
1518 0 : nX += mrViewBox.GetX();
1519 0 : nY += mrViewBox.GetY();
1520 : }
1521 0 : }
1522 :
1523 : //#define TEST_QUADRATIC_CURVES
1524 : #ifdef TEST_QUADRATIC_CURVES
1525 : // To be able to test quadratic curve code: The code concerning to
1526 : // bDoTestHere can be used (see below). Construct shapes which have their control
1527 : // points on equal coordinates. When these are written, they can be
1528 : // forced to create correct 'Q' and 'T' statements using this flag.
1529 : // These may then be tested for import/exporting.
1530 : static bool bDoTestHere(true);
1531 : #endif // TEST_QUADRATIC_CURVES
1532 :
1533 0 : void SdXMLImExSvgDElement::AddPolygon(
1534 : drawing::PointSequence* pPoints,
1535 : drawing::FlagSequence* pFlags,
1536 : const awt::Point& rObjectPos,
1537 : const awt::Size& rObjectSize,
1538 : bool bClosed)
1539 : {
1540 : // Leaving the export stuff for the while, should eventually also
1541 : // consolidated with basegfx svg support
1542 : DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)");
1543 :
1544 0 : sal_Int32 nCnt(pPoints->getLength());
1545 :
1546 : // #104076# Convert to string only when at last one point included
1547 0 : if(nCnt > 0)
1548 : {
1549 : // append polygon to string
1550 0 : OUString aNewString;
1551 0 : sal_Unicode aLastCommand = ' ';
1552 0 : awt::Point* pPointArray = pPoints->getArray();
1553 :
1554 : // are the flags used at all? If not forget about them
1555 0 : if(pFlags)
1556 : {
1557 0 : sal_Int32 nFlagCnt(pFlags->getLength());
1558 :
1559 0 : if(nFlagCnt)
1560 : {
1561 0 : bool bFlagsUsed(false);
1562 0 : drawing::PolygonFlags* pFlagArray = pFlags->getArray();
1563 :
1564 0 : for(sal_Int32 a(0); !bFlagsUsed && a < nFlagCnt; a++)
1565 0 : if(drawing::PolygonFlags_NORMAL != *pFlagArray++)
1566 0 : bFlagsUsed = true;
1567 :
1568 0 : if(!bFlagsUsed)
1569 0 : pFlags = 0L;
1570 : }
1571 : else
1572 : {
1573 0 : pFlags = 0L;
1574 : }
1575 : }
1576 :
1577 : // object size and ViewBox size different?
1578 0 : bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
1579 0 : || rObjectSize.Height != mrViewBox.GetHeight());
1580 0 : bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
1581 :
1582 : // #87202# rework of point reduction:
1583 : // Test for Last point same -> closed, ignore last point. Take
1584 : // some more circumstances in account when looking at curve segments.
1585 0 : drawing::PolygonFlags* pFlagArray = (pFlags) ? pFlags->getArray() : 0L;
1586 0 : if((pPointArray->X == (pPointArray + (nCnt - 1))->X) && (pPointArray->Y == (pPointArray + (nCnt - 1))->Y))
1587 : {
1588 0 : 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 0 : nCnt--;
1604 : }
1605 : }
1606 :
1607 : // bezier poly, handle curves
1608 0 : bool bDidWriteStart(false);
1609 0 : sal_Int32 nStartX(0), nStartY(0);
1610 :
1611 0 : for(sal_Int32 a(0L); a < nCnt; a++)
1612 : {
1613 0 : if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray)
1614 : {
1615 0 : bool bDidWriteAsCurve(false);
1616 :
1617 0 : if(bDidWriteStart)
1618 : {
1619 0 : 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 += OUString(sal_Unicode('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 += OUString(sal_Unicode('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 += OUString(sal_Unicode('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 += OUString(sal_Unicode('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('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 0 : 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 0 : mrViewBox, bScale, bTranslate);
1990 :
1991 0 : if(bDidWriteStart)
1992 : {
1993 : // write as normal point
1994 0 : if(mnLastX == nX)
1995 : {
1996 0 : if(mbRelative)
1997 : {
1998 0 : if(aLastCommand != sal_Unicode('v'))
1999 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('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 += rtl::OUString(static_cast<sal_Unicode>('V'));
2009 :
2010 0 : Imp_PutNumberCharWithSpace(aNewString, nY);
2011 :
2012 0 : aLastCommand = sal_Unicode('V');
2013 : }
2014 : }
2015 0 : else if(mnLastY == nY)
2016 : {
2017 0 : if(mbRelative)
2018 : {
2019 0 : if(aLastCommand != sal_Unicode('h'))
2020 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('h'));
2021 :
2022 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2023 :
2024 0 : aLastCommand = sal_Unicode('h');
2025 : }
2026 : else
2027 : {
2028 0 : if(aLastCommand != sal_Unicode('H'))
2029 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('H'));
2030 :
2031 0 : Imp_PutNumberCharWithSpace(aNewString, nX);
2032 :
2033 0 : aLastCommand = sal_Unicode('H');
2034 : }
2035 : }
2036 : else
2037 : {
2038 0 : if(mbRelative)
2039 : {
2040 0 : if(aLastCommand != sal_Unicode('l'))
2041 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('l'));
2042 :
2043 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2044 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2045 :
2046 0 : aLastCommand = sal_Unicode('l');
2047 : }
2048 : else
2049 : {
2050 0 : if(aLastCommand != sal_Unicode('L'))
2051 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('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 0 : if(mbRelative)
2064 : {
2065 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('m'));
2066 :
2067 0 : Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX);
2068 0 : Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY);
2069 :
2070 0 : aLastCommand = sal_Unicode('l');
2071 : }
2072 : else
2073 : {
2074 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('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 0 : bDidWriteStart = true;
2084 0 : nStartX = nX;
2085 0 : nStartY = nY;
2086 : }
2087 :
2088 : // remember new last position
2089 0 : mnLastX = nX;
2090 0 : mnLastY = nY;
2091 : }
2092 : }
2093 :
2094 : // next point
2095 0 : pPointArray++;
2096 0 : pFlagArray++;
2097 : }
2098 :
2099 : // close path if closed poly
2100 0 : if(bClosed)
2101 : {
2102 0 : if(mbRelative)
2103 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('z'));
2104 : else
2105 0 : aNewString += rtl::OUString(static_cast<sal_Unicode>('Z'));
2106 :
2107 : // update current point - we're back at the start
2108 0 : if( bDidWriteStart )
2109 : {
2110 0 : mnLastX = nStartX;
2111 0 : mnLastY = nStartY;
2112 : }
2113 : }
2114 :
2115 : // append new string
2116 0 : msString += aNewString;
2117 : }
2118 0 : }
2119 :
2120 7 : SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew,
2121 : const SdXMLImExViewBox& rViewBox,
2122 : const awt::Point& rObjectPos,
2123 : const awt::Size& rObjectSize,
2124 : const SvXMLImport& rImport)
2125 : : msString( rNew ),
2126 : mrViewBox( rViewBox ),
2127 : mbIsClosed( false ),
2128 : mbIsCurve( false ),
2129 : mbRelative( true ),
2130 : mnLastX( 0L ),
2131 : mnLastY( 0L ),
2132 7 : maPoly()
2133 : {
2134 7 : bool bWrongPositionAfterZ( false );
2135 7 : sal_Int32 nUPD( 0 );
2136 7 : sal_Int32 nBuildId( 0 );
2137 7 : if ( rImport.getBuildIds( nUPD, nBuildId ) &&
2138 : ( ( nUPD == 641 ) || ( nUPD == 645 ) || ( nUPD == 680 ) || ( nUPD == 300 ) ||
2139 : ( nUPD == 310 ) || ( nUPD == 320 ) || ( nUPD == 330 ) || ( nUPD == 340 ) ||
2140 : ( nUPD == 350 && nBuildId < 202 ) ) )
2141 : {
2142 6 : bWrongPositionAfterZ = true;
2143 : }
2144 :
2145 : // convert string to polygon
2146 7 : basegfx::B2DPolyPolygon aPoly;
2147 7 : basegfx::tools::importFromSvgD(aPoly,msString,bWrongPositionAfterZ);
2148 :
2149 7 : mbIsCurve = aPoly.areControlPointsUsed();
2150 7 : mbIsClosed = aPoly.isClosed();
2151 :
2152 : // object size and ViewBox size different?
2153 7 : basegfx::B2DHomMatrix aTransform;
2154 7 : const bool bScale(rObjectSize.Width != mrViewBox.GetWidth()
2155 14 : || rObjectSize.Height != mrViewBox.GetHeight());
2156 7 : const bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L);
2157 :
2158 7 : if( bTranslate )
2159 : aTransform.translate(
2160 0 : -mrViewBox.GetX(),
2161 0 : -mrViewBox.GetY());
2162 7 : if( bScale )
2163 : aTransform.scale(
2164 0 : (mrViewBox.GetWidth() ? rObjectSize.Width / mrViewBox.GetWidth() : 0),
2165 0 : (mrViewBox.GetHeight() ? rObjectSize.Height / mrViewBox.GetHeight() : 0));
2166 7 : aTransform.translate( rObjectPos.X, rObjectPos.Y );
2167 7 : aPoly.transform(aTransform);
2168 :
2169 7 : basegfx::unotools::b2DPolyPolygonToPolyPolygonBezier(aPoly,maPoly);
2170 7 : }
2171 :
2172 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|