LCOV - code coverage report
Current view: top level - libreoffice/xmloff/source/draw - xexptran.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 191 927 20.6 %
Date: 2012-12-27 Functions: 17 59 28.8 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.10