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

Generated by: LCOV version 1.10