| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmloff.hxx" |
| #include "xexptran.hxx" |
| #include <tools/debug.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <xmloff/xmluconv.hxx> |
| #include <tools/gen.hxx> |
| #include <basegfx/vector/b2dvector.hxx> |
| #include <basegfx/matrix/b2dhommatrix.hxx> |
| #include <basegfx/tuple/b3dtuple.hxx> |
| #include <basegfx/matrix/b3dhommatrix.hxx> |
| #include <tools/string.hxx> |
| |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| |
| using namespace ::com::sun::star; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Defines |
| |
| #define BORDER_INTEGERS_ARE_EQUAL (4) |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // Predeclarations |
| |
| void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen); |
| void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection); |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // parsing help functions for simple chars |
| void Imp_SkipSpaces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen) |
| { |
| while(rPos < nLen |
| && sal_Unicode(' ') == rStr[rPos]) |
| rPos++; |
| } |
| |
| void Imp_SkipSpacesAndOpeningBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen) |
| { |
| while(rPos < nLen |
| && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode('(') == rStr[rPos])) |
| rPos++; |
| } |
| |
| void Imp_SkipSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen) |
| { |
| while(rPos < nLen |
| && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(',') == rStr[rPos])) |
| rPos++; |
| } |
| |
| void Imp_SkipSpacesAndClosingBraces(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen) |
| { |
| while(rPos < nLen |
| && (sal_Unicode(' ') == rStr[rPos] || sal_Unicode(')') == rStr[rPos])) |
| rPos++; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // parsing help functions for integer numbers |
| |
| bool Imp_IsOnNumberChar(const OUString& rStr, const sal_Int32 nPos, bool bSignAllowed = true) |
| { |
| sal_Unicode aChar(rStr[nPos]); |
| |
| if((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) |
| || (bSignAllowed && sal_Unicode('+') == aChar) |
| || (bSignAllowed && sal_Unicode('-') == aChar) |
| ) |
| return true; |
| return false; |
| } |
| |
| bool Imp_IsOnUnitChar(const OUString& rStr, const sal_Int32 nPos) |
| { |
| sal_Unicode aChar(rStr[nPos]); |
| |
| if((sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar) |
| || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar) |
| || sal_Unicode('%') == aChar |
| ) |
| return true; |
| return false; |
| } |
| |
| void Imp_SkipNumber(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen) |
| { |
| bool bSignAllowed(true); |
| |
| while(rPos < nLen && Imp_IsOnNumberChar(rStr, rPos, bSignAllowed)) |
| { |
| bSignAllowed = false; |
| rPos++; |
| } |
| } |
| |
| void Imp_SkipNumberAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, |
| const sal_Int32 nLen) |
| { |
| Imp_SkipNumber(rStr, rPos, nLen); |
| Imp_SkipSpacesAndCommas(rStr, rPos, nLen); |
| } |
| |
| // #100617# Allow to skip doubles, too. |
| void Imp_SkipDoubleAndSpacesAndCommas(const OUString& rStr, sal_Int32& rPos, |
| const sal_Int32 nLen) |
| { |
| Imp_SkipDouble(rStr, rPos, nLen); |
| Imp_SkipSpacesAndCommas(rStr, rPos, nLen); |
| } |
| |
| void Imp_PutNumberChar(OUString& rStr, sal_Int32 nValue) |
| { |
| OUStringBuffer sStringBuffer; |
| SvXMLUnitConverter::convertNumber(sStringBuffer, nValue); |
| rStr += OUString(sStringBuffer.makeStringAndClear()); |
| } |
| |
| void Imp_PutNumberCharWithSpace(OUString& rStr, sal_Int32 nValue) |
| { |
| const sal_Int32 aLen(rStr.getLength()); |
| if(aLen) |
| if(Imp_IsOnNumberChar(rStr, aLen - 1, false) && nValue >= 0) |
| rStr += String(sal_Unicode(' ')); |
| Imp_PutNumberChar(rStr, nValue); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // parsing help functions for double numbers |
| |
| void Imp_SkipDouble(const OUString& rStr, sal_Int32& rPos, const sal_Int32) |
| { |
| sal_Unicode aChar(rStr[rPos]); |
| |
| if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) |
| aChar = rStr[++rPos]; |
| |
| while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) |
| || sal_Unicode('.') == aChar) |
| { |
| aChar = rStr[++rPos]; |
| } |
| |
| if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar) |
| { |
| aChar = rStr[++rPos]; |
| |
| if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) |
| aChar = rStr[++rPos]; |
| |
| while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) |
| { |
| aChar = rStr[++rPos]; |
| } |
| } |
| } |
| |
| double Imp_GetDoubleChar(const OUString& rStr, sal_Int32& rPos, const sal_Int32 nLen, |
| const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false) |
| { |
| sal_Unicode aChar(rStr[rPos]); |
| OUStringBuffer sNumberString; |
| |
| if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) |
| { |
| sNumberString.append(rStr[rPos]); |
| aChar = rStr[++rPos]; |
| } |
| |
| while((sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) |
| || sal_Unicode('.') == aChar) |
| { |
| sNumberString.append(rStr[rPos]); |
| aChar = rStr[++rPos]; |
| } |
| |
| if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar) |
| { |
| sNumberString.append(rStr[rPos]); |
| aChar = rStr[++rPos]; |
| |
| if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar) |
| { |
| sNumberString.append(rStr[rPos]); |
| aChar = rStr[++rPos]; |
| } |
| |
| while(sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) |
| { |
| sNumberString.append(rStr[rPos]); |
| aChar = rStr[++rPos]; |
| } |
| } |
| |
| if(bLookForUnits) |
| { |
| Imp_SkipSpaces(rStr, rPos, nLen); |
| while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos)) |
| sNumberString.append(rStr[rPos++]); |
| } |
| |
| if(sNumberString.getLength()) |
| { |
| if(bLookForUnits) |
| rConv.convertDouble(fRetval, sNumberString.makeStringAndClear(), true); |
| else |
| rConv.convertDouble(fRetval, sNumberString.makeStringAndClear()); |
| } |
| |
| return fRetval; |
| } |
| |
| void Imp_PutDoubleChar(OUString& rStr, const SvXMLUnitConverter& rConv, double fValue, |
| bool bConvertUnits = false) |
| { |
| OUStringBuffer sStringBuffer; |
| |
| if(bConvertUnits) |
| rConv.convertDouble(sStringBuffer, fValue, true); |
| else |
| rConv.convertDouble(sStringBuffer, fValue); |
| |
| rStr += OUString(sStringBuffer.makeStringAndClear()); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // base class of all 2D transform objects |
| |
| struct ImpSdXMLExpTransObj2DBase |
| { |
| sal_uInt16 mnType; |
| ImpSdXMLExpTransObj2DBase(sal_uInt16 nType) |
| : mnType(nType) {} |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // possible object types for 2D |
| |
| #define IMP_SDXMLEXP_TRANSOBJ2D_ROTATE 0x0000 |
| #define IMP_SDXMLEXP_TRANSOBJ2D_SCALE 0x0001 |
| #define IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE 0x0002 |
| #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWX 0x0003 |
| #define IMP_SDXMLEXP_TRANSOBJ2D_SKEWY 0x0004 |
| #define IMP_SDXMLEXP_TRANSOBJ2D_MATRIX 0x0005 |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // classes of objects, different sizes |
| |
| struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase |
| { |
| double mfRotate; |
| ImpSdXMLExpTransObj2DRotate(double fVal) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase |
| { |
| ::basegfx::B2DTuple maScale; |
| ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {} |
| }; |
| struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase |
| { |
| ::basegfx::B2DTuple maTranslate; |
| ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {} |
| }; |
| struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase |
| { |
| double mfSkewX; |
| ImpSdXMLExpTransObj2DSkewX(double fVal) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase |
| { |
| double mfSkewY; |
| ImpSdXMLExpTransObj2DSkewY(double fVal) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase |
| { |
| ::basegfx::B2DHomMatrix maMatrix; |
| ImpSdXMLExpTransObj2DMatrix(const ::basegfx::B2DHomMatrix& rNew) |
| : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(rNew) {} |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // delete all entries in list |
| |
| void SdXMLImExTransform2D::EmptyList() |
| { |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj2DBase* pObj = maList[a]; |
| |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE : |
| { |
| delete (ImpSdXMLExpTransObj2DRotate*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SCALE : |
| { |
| delete (ImpSdXMLExpTransObj2DScale*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE : |
| { |
| delete (ImpSdXMLExpTransObj2DTranslate*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : |
| { |
| delete (ImpSdXMLExpTransObj2DSkewX*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : |
| { |
| delete (ImpSdXMLExpTransObj2DSkewY*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : |
| { |
| delete (ImpSdXMLExpTransObj2DMatrix*)pObj; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform2D: impossible entry!"); |
| break; |
| } |
| } |
| } |
| |
| maList.clear(); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // add members |
| |
| void SdXMLImExTransform2D::AddRotate(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DRotate(fNew)); |
| } |
| |
| void SdXMLImExTransform2D::AddScale(const ::basegfx::B2DTuple& rNew) |
| { |
| if(1.0 != rNew.getX() || 1.0 != rNew.getY()) |
| maList.push_back(new ImpSdXMLExpTransObj2DScale(rNew)); |
| } |
| |
| void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew) |
| { |
| if(!rNew.equalZero()) |
| maList.push_back(new ImpSdXMLExpTransObj2DTranslate(rNew)); |
| } |
| |
| void SdXMLImExTransform2D::AddSkewX(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fNew)); |
| } |
| |
| void SdXMLImExTransform2D::AddSkewY(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fNew)); |
| } |
| |
| void SdXMLImExTransform2D::AddMatrix(const ::basegfx::B2DHomMatrix& rNew) |
| { |
| if(!rNew.isIdentity()) |
| maList.push_back(new ImpSdXMLExpTransObj2DMatrix(rNew)); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // gen string for export |
| const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv) |
| { |
| OUString aNewString; |
| OUString aClosingBrace(sal_Unicode(')')); |
| OUString aEmptySpace(sal_Unicode(' ')); |
| |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj2DBase* pObj = maList[a]; |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE : |
| { |
| aNewString += OUString::createFromAscii("rotate ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SCALE : |
| { |
| aNewString += OUString::createFromAscii("scale ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getX()); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale.getY()); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE : |
| { |
| aNewString += OUString::createFromAscii("translate ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getX(), true); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate.getY(), true); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : |
| { |
| aNewString += OUString::createFromAscii("skewX ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : |
| { |
| aNewString += OUString::createFromAscii("skewY ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : |
| { |
| aNewString += OUString::createFromAscii("matrix ("); |
| |
| // a |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 0)); |
| aNewString += aEmptySpace; |
| |
| // b |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 0)); |
| aNewString += aEmptySpace; |
| |
| // c |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 1)); |
| aNewString += aEmptySpace; |
| |
| // d |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 1)); |
| aNewString += aEmptySpace; |
| |
| // e |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(0, 2), true); |
| aNewString += aEmptySpace; |
| |
| // f |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix.get(1, 2), true); |
| |
| aNewString += aClosingBrace; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform2D: impossible entry!"); |
| break; |
| } |
| } |
| |
| // if not the last entry, add one space to next tag |
| if(a + 1UL != maList.size()) |
| { |
| aNewString += aEmptySpace; |
| } |
| } |
| |
| // fill string form OUString |
| msString = aNewString; |
| |
| return msString; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // for Import: constructor with string, parses it and generates entries |
| SdXMLImExTransform2D::SdXMLImExTransform2D(const OUString& rNew, const SvXMLUnitConverter& rConv) |
| { |
| SetString(rNew, rConv); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // sets new string, parses it and generates entries |
| void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv) |
| { |
| msString = rNew; |
| EmptyList(); |
| |
| if(msString.getLength()) |
| { |
| const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength()); |
| const sal_Int32 nLen(aStr.getLength()); |
| |
| const OUString aString_rotate(OUString::createFromAscii("rotate")); |
| const OUString aString_scale(OUString::createFromAscii("scale")); |
| const OUString aString_translate(OUString::createFromAscii("translate")); |
| const OUString aString_skewX(OUString::createFromAscii("skewX")); |
| const OUString aString_skewY(OUString::createFromAscii("skewY")); |
| const OUString aString_matrix(OUString::createFromAscii("matrix")); |
| |
| sal_Int32 nPos(0); |
| |
| while(nPos < nLen) |
| { |
| // skip spaces |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // look for tag |
| if(nPos < nLen) |
| { |
| if(nPos == aStr.indexOf(aString_rotate, nPos)) |
| { |
| double fValue(0.0); |
| nPos += 6; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DRotate(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_scale, nPos)) |
| { |
| ::basegfx::B2DTuple aValue(1.0, 1.0); |
| nPos += 5; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX())); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY())); |
| |
| if(aValue.getX() != 1.0 || aValue.getY() != 1.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DScale(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_translate, nPos)) |
| { |
| ::basegfx::B2DTuple aValue; |
| nPos += 9; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true)); |
| |
| if(!aValue.equalZero()) |
| maList.push_back(new ImpSdXMLExpTransObj2DTranslate(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_skewX, nPos)) |
| { |
| double fValue(0.0); |
| nPos += 5; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DSkewX(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_skewY, nPos)) |
| { |
| double fValue(0.0); |
| nPos += 5; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj2DSkewY(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_matrix, nPos)) |
| { |
| ::basegfx::B2DHomMatrix aValue; |
| |
| nPos += 6; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| |
| // a |
| aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // b |
| aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // c |
| aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // d |
| aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // e |
| aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // f |
| aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| if(!aValue.isIdentity()) |
| maList.push_back(new ImpSdXMLExpTransObj2DMatrix(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else |
| { |
| nPos++; |
| } |
| } |
| } |
| } |
| } |
| |
| void SdXMLImExTransform2D::GetFullTransform(::basegfx::B2DHomMatrix& rFullTrans) |
| { |
| rFullTrans.identity(); |
| |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj2DBase* pObj = maList[a]; |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE : |
| { |
| // #i78696# |
| // mfRotate is mathematically wrong oriented since we export/import the angle |
| // values mirrored. This error is fixed in the API, but not yet in the FileFormat. |
| // For the FileFormat there is a follow-up task (#i78698#) to fix this in the next |
| // ODF FileFormat version. For now - to emulate the old behaviour - it is necessary |
| // to mirror the value here |
| rFullTrans.rotate(((ImpSdXMLExpTransObj2DRotate*)pObj)->mfRotate * -1.0); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SCALE : |
| { |
| const ::basegfx::B2DTuple& rScale = ((ImpSdXMLExpTransObj2DScale*)pObj)->maScale; |
| rFullTrans.scale(rScale.getX(), rScale.getY()); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE : |
| { |
| const ::basegfx::B2DTuple& rTranslate = ((ImpSdXMLExpTransObj2DTranslate*)pObj)->maTranslate; |
| rFullTrans.translate(rTranslate.getX(), rTranslate.getY()); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : |
| { |
| rFullTrans.shearX(tan(((ImpSdXMLExpTransObj2DSkewX*)pObj)->mfSkewX)); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : |
| { |
| rFullTrans.shearY(tan(((ImpSdXMLExpTransObj2DSkewY*)pObj)->mfSkewY)); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : |
| { |
| rFullTrans *= ((ImpSdXMLExpTransObj2DMatrix*)pObj)->maMatrix; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform2D: impossible entry!"); |
| break; |
| } |
| } |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // base class of all 3D transform objects |
| |
| struct ImpSdXMLExpTransObj3DBase |
| { |
| sal_uInt16 mnType; |
| ImpSdXMLExpTransObj3DBase(sal_uInt16 nType) |
| : mnType(nType) {} |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // possible object types for 3D |
| |
| #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X 0x0000 |
| #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y 0x0001 |
| #define IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z 0x0002 |
| #define IMP_SDXMLEXP_TRANSOBJ3D_SCALE 0x0003 |
| #define IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE 0x0004 |
| #define IMP_SDXMLEXP_TRANSOBJ3D_MATRIX 0x0005 |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // classes of objects, different sizes |
| |
| struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase |
| { |
| double mfRotateX; |
| ImpSdXMLExpTransObj3DRotateX(double fVal) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase |
| { |
| double mfRotateY; |
| ImpSdXMLExpTransObj3DRotateY(double fVal) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase |
| { |
| double mfRotateZ; |
| ImpSdXMLExpTransObj3DRotateZ(double fVal) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {} |
| }; |
| struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase |
| { |
| ::basegfx::B3DTuple maScale; |
| ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {} |
| }; |
| struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase |
| { |
| ::basegfx::B3DTuple maTranslate; |
| ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {} |
| }; |
| struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase |
| { |
| ::basegfx::B3DHomMatrix maMatrix; |
| ImpSdXMLExpTransObj3DMatrix(const ::basegfx::B3DHomMatrix& rNew) |
| : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(rNew) {} |
| }; |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| // delete all entries in list |
| |
| void SdXMLImExTransform3D::EmptyList() |
| { |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj3DBase* pObj = maList[a]; |
| |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X : |
| { |
| delete (ImpSdXMLExpTransObj3DRotateX*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y : |
| { |
| delete (ImpSdXMLExpTransObj3DRotateY*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z : |
| { |
| delete (ImpSdXMLExpTransObj3DRotateZ*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_SCALE : |
| { |
| delete (ImpSdXMLExpTransObj3DScale*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE : |
| { |
| delete (ImpSdXMLExpTransObj3DTranslate*)pObj; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX : |
| { |
| delete (ImpSdXMLExpTransObj3DMatrix*)pObj; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform3D: impossible entry!"); |
| break; |
| } |
| } |
| } |
| |
| maList.clear(); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // add members |
| |
| void SdXMLImExTransform3D::AddRotateX(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddRotateY(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddRotateZ(double fNew) |
| { |
| if(fNew != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddScale(const ::basegfx::B3DTuple& rNew) |
| { |
| if(1.0 != rNew.getX() || 1.0 != rNew.getY() || 1.0 != rNew.getZ()) |
| maList.push_back(new ImpSdXMLExpTransObj3DScale(rNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddTranslate(const ::basegfx::B3DTuple& rNew) |
| { |
| if(!rNew.equalZero()) |
| maList.push_back(new ImpSdXMLExpTransObj3DTranslate(rNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew) |
| { |
| if(!rNew.isIdentity()) |
| maList.push_back(new ImpSdXMLExpTransObj3DMatrix(rNew)); |
| } |
| |
| void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat) |
| { |
| ::basegfx::B3DHomMatrix aExportMatrix; |
| |
| aExportMatrix.set(0, 0, xHomMat.Line1.Column1); |
| aExportMatrix.set(0, 1, xHomMat.Line1.Column2); |
| aExportMatrix.set(0, 2, xHomMat.Line1.Column3); |
| aExportMatrix.set(0, 3, xHomMat.Line1.Column4); |
| aExportMatrix.set(1, 0, xHomMat.Line2.Column1); |
| aExportMatrix.set(1, 1, xHomMat.Line2.Column2); |
| aExportMatrix.set(1, 2, xHomMat.Line2.Column3); |
| aExportMatrix.set(1, 3, xHomMat.Line2.Column4); |
| aExportMatrix.set(2, 0, xHomMat.Line3.Column1); |
| aExportMatrix.set(2, 1, xHomMat.Line3.Column2); |
| aExportMatrix.set(2, 2, xHomMat.Line3.Column3); |
| aExportMatrix.set(2, 3, xHomMat.Line3.Column4); |
| |
| AddMatrix(aExportMatrix); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // gen string for export |
| const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv) |
| { |
| OUString aNewString; |
| OUString aClosingBrace(sal_Unicode(')')); |
| OUString aEmptySpace(sal_Unicode(' ')); |
| |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj3DBase* pObj = maList[a]; |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X : |
| { |
| aNewString += OUString::createFromAscii("rotatex ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y : |
| { |
| aNewString += OUString::createFromAscii("rotatey ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z : |
| { |
| aNewString += OUString::createFromAscii("rotatez ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_SCALE : |
| { |
| aNewString += OUString::createFromAscii("scale ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getX()); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getY()); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale.getZ()); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE : |
| { |
| aNewString += OUString::createFromAscii("translate ("); |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getX(), true); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getY(), true); |
| aNewString += aEmptySpace; |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate.getZ(), true); |
| aNewString += aClosingBrace; |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX : |
| { |
| aNewString += OUString::createFromAscii("matrix ("); |
| |
| // a |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 0)); |
| aNewString += aEmptySpace; |
| |
| // b |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 0)); |
| aNewString += aEmptySpace; |
| |
| // c |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 0)); |
| aNewString += aEmptySpace; |
| |
| // d |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 1)); |
| aNewString += aEmptySpace; |
| |
| // e |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 1)); |
| aNewString += aEmptySpace; |
| |
| // f |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 1)); |
| aNewString += aEmptySpace; |
| |
| // g |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 2)); |
| aNewString += aEmptySpace; |
| |
| // h |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 2)); |
| aNewString += aEmptySpace; |
| |
| // i |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 2)); |
| aNewString += aEmptySpace; |
| |
| // j |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(0, 3), true); |
| aNewString += aEmptySpace; |
| |
| // k |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(1, 3), true); |
| aNewString += aEmptySpace; |
| |
| // l |
| Imp_PutDoubleChar(aNewString, rConv, ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix.get(2, 3), true); |
| |
| aNewString += aClosingBrace; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform3D: impossible entry!"); |
| break; |
| } |
| } |
| |
| // if not the last entry, add one space to next tag |
| if(a + 1UL != maList.size()) |
| { |
| aNewString += aEmptySpace; |
| } |
| } |
| |
| // fill string form OUString |
| msString = aNewString; |
| |
| return msString; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // for Import: constructor with string, parses it and generates entries |
| SdXMLImExTransform3D::SdXMLImExTransform3D(const OUString& rNew, const SvXMLUnitConverter& rConv) |
| { |
| SetString(rNew, rConv); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // sets new string, parses it and generates entries |
| void SdXMLImExTransform3D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv) |
| { |
| msString = rNew; |
| EmptyList(); |
| |
| if(msString.getLength()) |
| { |
| const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength()); |
| const sal_Int32 nLen(aStr.getLength()); |
| |
| const OUString aString_rotatex(OUString::createFromAscii("rotatex")); |
| const OUString aString_rotatey(OUString::createFromAscii("rotatey")); |
| const OUString aString_rotatez(OUString::createFromAscii("rotatez")); |
| const OUString aString_scale(OUString::createFromAscii("scale")); |
| const OUString aString_translate(OUString::createFromAscii("translate")); |
| const OUString aString_matrix(OUString::createFromAscii("matrix")); |
| |
| sal_Int32 nPos(0); |
| |
| while(nPos < nLen) |
| { |
| // skip spaces |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // look for tag |
| if(nPos < nLen) |
| { |
| if(nPos == aStr.indexOf(aString_rotatex, nPos)) |
| { |
| double fValue(0.0); |
| |
| nPos += 7; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateX(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_rotatey, nPos)) |
| { |
| double fValue(0.0); |
| |
| nPos += 7; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateY(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_rotatez, nPos)) |
| { |
| double fValue(0.0); |
| |
| nPos += 7; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| fValue = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, fValue); |
| if(fValue != 0.0) |
| maList.push_back(new ImpSdXMLExpTransObj3DRotateZ(fValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_scale, nPos)) |
| { |
| ::basegfx::B3DTuple aValue(1.0, 1.0, 1.0); |
| |
| nPos += 5; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX())); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY())); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ())); |
| |
| if(1.0 != aValue.getX() || 1.0 != aValue.getY() || 1.0 != aValue.getZ()) |
| maList.push_back(new ImpSdXMLExpTransObj3DScale(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_translate, nPos)) |
| { |
| ::basegfx::B3DTuple aValue; |
| |
| nPos += 9; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| aValue.setX(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getX(), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setY(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getY(), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| aValue.setZ(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.getZ(), true)); |
| |
| if(!aValue.equalZero()) |
| maList.push_back(new ImpSdXMLExpTransObj3DTranslate(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else if(nPos == aStr.indexOf(aString_matrix, nPos)) |
| { |
| ::basegfx::B3DHomMatrix aValue; |
| |
| nPos += 6; |
| Imp_SkipSpacesAndOpeningBraces(aStr, nPos, nLen); |
| |
| // a |
| aValue.set(0, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 0))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // b |
| aValue.set(1, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 0))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // c |
| aValue.set(2, 0, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 0))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // d |
| aValue.set(0, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 1))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // e |
| aValue.set(1, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 1))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // f |
| aValue.set(2, 1, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 1))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // g |
| aValue.set(0, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 2))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // h |
| aValue.set(1, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 2))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // i |
| aValue.set(2, 2, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 2))); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // j |
| aValue.set(0, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(0, 3), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // k |
| aValue.set(1, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(1, 3), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // l |
| aValue.set(2, 3, Imp_GetDoubleChar(aStr, nPos, nLen, rConv, aValue.get(2, 3), true)); |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| if(!aValue.isIdentity()) |
| maList.push_back(new ImpSdXMLExpTransObj3DMatrix(aValue)); |
| |
| Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); |
| } |
| else |
| { |
| nPos++; |
| } |
| } |
| } |
| } |
| } |
| |
| bool SdXMLImExTransform3D::GetFullHomogenTransform(com::sun::star::drawing::HomogenMatrix& xHomMat) |
| { |
| ::basegfx::B3DHomMatrix aFullTransform; |
| GetFullTransform(aFullTransform); |
| |
| if(!aFullTransform.isIdentity()) |
| { |
| xHomMat.Line1.Column1 = aFullTransform.get(0, 0); |
| xHomMat.Line1.Column2 = aFullTransform.get(0, 1); |
| xHomMat.Line1.Column3 = aFullTransform.get(0, 2); |
| xHomMat.Line1.Column4 = aFullTransform.get(0, 3); |
| |
| xHomMat.Line2.Column1 = aFullTransform.get(1, 0); |
| xHomMat.Line2.Column2 = aFullTransform.get(1, 1); |
| xHomMat.Line2.Column3 = aFullTransform.get(1, 2); |
| xHomMat.Line2.Column4 = aFullTransform.get(1, 3); |
| |
| xHomMat.Line3.Column1 = aFullTransform.get(2, 0); |
| xHomMat.Line3.Column2 = aFullTransform.get(2, 1); |
| xHomMat.Line3.Column3 = aFullTransform.get(2, 2); |
| xHomMat.Line3.Column4 = aFullTransform.get(2, 3); |
| |
| xHomMat.Line4.Column1 = aFullTransform.get(3, 0); |
| xHomMat.Line4.Column2 = aFullTransform.get(3, 1); |
| xHomMat.Line4.Column3 = aFullTransform.get(3, 2); |
| xHomMat.Line4.Column4 = aFullTransform.get(3, 3); |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans) |
| { |
| rFullTrans.identity(); |
| |
| const sal_uInt32 nCount = maList.size(); |
| for(sal_uInt32 a(0L); a < nCount; a++) |
| { |
| ImpSdXMLExpTransObj3DBase* pObj = maList[a]; |
| switch(pObj->mnType) |
| { |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X : |
| { |
| rFullTrans.rotate(((ImpSdXMLExpTransObj3DRotateX*)pObj)->mfRotateX, 0.0, 0.0); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y : |
| { |
| rFullTrans.rotate(0.0, ((ImpSdXMLExpTransObj3DRotateY*)pObj)->mfRotateY, 0.0); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z : |
| { |
| rFullTrans.rotate(0.0, 0.0, ((ImpSdXMLExpTransObj3DRotateZ*)pObj)->mfRotateZ); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_SCALE : |
| { |
| const ::basegfx::B3DTuple& rScale = ((ImpSdXMLExpTransObj3DScale*)pObj)->maScale; |
| rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ()); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE : |
| { |
| const ::basegfx::B3DTuple& rTranslate = ((ImpSdXMLExpTransObj3DTranslate*)pObj)->maTranslate; |
| rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ()); |
| break; |
| } |
| case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX : |
| { |
| rFullTrans *= ((ImpSdXMLExpTransObj3DMatrix*)pObj)->maMatrix; |
| break; |
| } |
| default : |
| { |
| DBG_ERROR("SdXMLImExTransform3D: impossible entry!"); |
| break; |
| } |
| } |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| SdXMLImExViewBox::SdXMLImExViewBox(sal_Int32 nX, sal_Int32 nY, sal_Int32 nW, sal_Int32 nH) |
| : mnX( nX ), |
| mnY( nY ), |
| mnW( nW ), |
| mnH( nH ) |
| { |
| } |
| |
| // #100617# Asked vincent hardy: svg:viewBox values may be double precision. |
| SdXMLImExViewBox::SdXMLImExViewBox(const OUString& rNew, const SvXMLUnitConverter& rConv) |
| : msString(rNew), |
| mnX( 0L ), |
| mnY( 0L ), |
| mnW( 1000L ), |
| mnH( 1000L ) |
| { |
| if(msString.getLength()) |
| { |
| const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength()); |
| const sal_Int32 nLen(aStr.getLength()); |
| sal_Int32 nPos(0); |
| |
| // skip starting spaces |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // get mX, #100617# be prepared for doubles |
| mnX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnX)); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // get mY, #100617# be prepared for doubles |
| mnY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnY)); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // get mW, #100617# be prepared for doubles |
| mnW = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnW)); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // get mH, #100617# be prepared for doubles |
| mnH = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)mnH)); |
| } |
| } |
| |
| const OUString& SdXMLImExViewBox::GetExportString() |
| { |
| OUString aNewString; |
| OUString aEmptySpace(sal_Unicode(' ')); |
| |
| Imp_PutNumberChar(aNewString, mnX); |
| aNewString += aEmptySpace; |
| |
| Imp_PutNumberChar(aNewString, mnY); |
| aNewString += aEmptySpace; |
| |
| Imp_PutNumberChar(aNewString, mnW); |
| aNewString += aEmptySpace; |
| |
| Imp_PutNumberChar(aNewString, mnH); |
| |
| // set new string |
| msString = aNewString; |
| |
| return msString; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| SdXMLImExPointsElement::SdXMLImExPointsElement(drawing::PointSequence* pPoints, |
| const SdXMLImExViewBox& rViewBox, |
| const awt::Point& rObjectPos, |
| const awt::Size& rObjectSize, |
| // #96328# |
| const bool bClosed) |
| : maPoly( 0L ) |
| { |
| DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExPointsElement(!)"); |
| |
| // add polygon to string |
| sal_Int32 nCnt(pPoints->getLength()); |
| |
| // #104076# Convert to string only when at last one point included |
| if(nCnt > 0) |
| { |
| OUString aNewString; |
| awt::Point* pArray = pPoints->getArray(); |
| |
| // last point same? Ignore it. |
| // #96328# ...but only when polygon is CLOSED |
| if(bClosed && (pArray->X == (pArray + (nCnt - 1))->X) && (pArray->Y == (pArray + (nCnt - 1))->Y)) |
| nCnt--; |
| |
| // object size and ViewBox size different? |
| bool bScale(rObjectSize.Width != rViewBox.GetWidth() |
| || rObjectSize.Height != rViewBox.GetHeight()); |
| bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L); |
| |
| for(sal_Int32 a(0L); a < nCnt; a++) |
| { |
| // prepare coordinates |
| sal_Int32 nX( pArray->X - rObjectPos.X ); |
| sal_Int32 nY( pArray->Y - rObjectPos.Y ); |
| |
| if(bScale && rObjectSize.Width && rObjectSize.Height) |
| { |
| nX = (nX * rViewBox.GetWidth()) / rObjectSize.Width; |
| nY = (nY * rViewBox.GetHeight()) / rObjectSize.Height; |
| } |
| |
| if(bTranslate) |
| { |
| nX += rViewBox.GetX(); |
| nY += rViewBox.GetY(); |
| } |
| |
| // X and comma |
| Imp_PutNumberChar(aNewString, nX); |
| aNewString += String(sal_Unicode(',')); |
| |
| // Y and space (not for last) |
| Imp_PutNumberChar(aNewString, nY); |
| if(a + 1 != nCnt) |
| aNewString += String(sal_Unicode(' ')); |
| |
| // next point |
| pArray++; |
| } |
| |
| // set new string |
| msString = aNewString; |
| } |
| } |
| |
| // #100617# svg:polyline or svg:polygon values may be double precision. |
| SdXMLImExPointsElement::SdXMLImExPointsElement(const OUString& rNew, |
| const SdXMLImExViewBox& rViewBox, |
| const awt::Point& rObjectPos, |
| const awt::Size& rObjectSize, |
| const SvXMLUnitConverter& rConv) |
| : msString( rNew ), |
| maPoly( 0L ) |
| { |
| // convert string to polygon |
| const OUString aStr(msString.getStr(), (sal_uInt16)msString.getLength()); |
| const sal_Int32 nLen(aStr.getLength()); |
| sal_Int32 nPos(0); |
| sal_Int32 nNumPoints(0L); |
| |
| // skip starting spaces |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // count points in first loop |
| while(nPos < nLen) |
| { |
| // skip number, #100617# be prepared for doubles |
| Imp_SkipDouble(aStr, nPos, nLen); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // skip number, #100617# be prepared for doubles |
| Imp_SkipDouble(aStr, nPos, nLen); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // one more point |
| nNumPoints++; |
| } |
| |
| // second loop |
| if(nNumPoints) |
| { |
| nPos = 0; |
| maPoly.realloc(1); |
| drawing::PointSequence* pOuterSequence = maPoly.getArray(); |
| pOuterSequence->realloc(nNumPoints); |
| awt::Point* pInnerSequence = pOuterSequence->getArray(); |
| |
| // object size and ViewBox size different? |
| bool bScale(rObjectSize.Width != rViewBox.GetWidth() |
| || rObjectSize.Height != rViewBox.GetHeight()); |
| bool bTranslate(rViewBox.GetX() != 0L || rViewBox.GetY() != 0L); |
| |
| // skip starting spaces |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen) |
| { |
| // prepare new parameter pair |
| sal_Int32 nX(0L); |
| sal_Int32 nY(0L); |
| |
| // get mX, #100617# be prepared for doubles |
| nX = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nX)); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // get mY, #100617# be prepared for doubles |
| nY = FRound(Imp_GetDoubleChar(aStr, nPos, nLen, rConv, (double)nY)); |
| |
| // skip spaces and commas |
| Imp_SkipSpacesAndCommas(aStr, nPos, nLen); |
| |
| // prepare parameters |
| if(bTranslate) |
| { |
| nX -= rViewBox.GetX(); |
| nY -= rViewBox.GetY(); |
| } |
| |
| if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight() ) |
| { |
| nX = (nX * rObjectSize.Width) / rViewBox.GetWidth(); |
| nY = (nY * rObjectSize.Height) / rViewBox.GetHeight(); |
| } |
| |
| nX += rObjectPos.X; |
| nY += rObjectPos.Y; |
| |
| // add new point |
| *pInnerSequence = awt::Point( nX, nY ); |
| pInnerSequence++; |
| } |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| ////////////////////////////////////////////////////////////////////////////// |
| |
| SdXMLImExSvgDElement::SdXMLImExSvgDElement(const SdXMLImExViewBox& rViewBox) |
| : mrViewBox( rViewBox ), |
| mbIsClosed( false ), |
| mbIsCurve( false ), |
| mnLastX( 0L ), |
| mnLastY( 0L ), |
| maPoly( 0L ), |
| maFlag( 0L ) |
| { |
| } |
| |
| void Imp_GetPrevPos(awt::Point*& pPrevPos1, |
| drawing::PolygonFlags& aPrevFlag1, |
| const bool bClosed, awt::Point* pPoints, |
| drawing::PolygonFlags* pFlags, const sal_Int32 nPos, |
| const sal_Int32 nCnt, const sal_Int32 nAdd) |
| { |
| if(bClosed) |
| { |
| pPrevPos1 = pPoints + ((nPos + nCnt - nAdd) % nCnt); |
| aPrevFlag1 = *(pFlags + ((nPos + nCnt - nAdd) % nCnt)); |
| } |
| else if(nPos > (nAdd - 1)) |
| { |
| pPrevPos1 = pPoints + (nPos - nAdd); |
| aPrevFlag1 = *(pFlags + (nPos - nAdd)); |
| } |
| else |
| pPrevPos1 = 0L; |
| } |
| |
| void Imp_PrepareCoorExport(sal_Int32& nX, sal_Int32& nY, |
| const awt::Point* pPointArray, const awt::Point& rObjectPos, |
| const awt::Size& rObjectSize, const SdXMLImExViewBox& mrViewBox, |
| const bool bScale, const bool bTranslate) |
| { |
| nX = pPointArray->X - rObjectPos.X; |
| nY = pPointArray->Y - rObjectPos.Y; |
| |
| if(bScale && rObjectSize.Width && rObjectSize.Height ) |
| { |
| nX = (nX * mrViewBox.GetWidth()) / rObjectSize.Width; |
| nY = (nY * mrViewBox.GetHeight()) / rObjectSize.Height; |
| } |
| |
| if(bTranslate) |
| { |
| nX += mrViewBox.GetX(); |
| nY += mrViewBox.GetY(); |
| } |
| } |
| |
| //#define TEST_QUADRATIC_CURVES |
| #ifdef TEST_QUADRATIC_CURVES |
| // To be able to test quadratic curve code: The code concerning to |
| // bDoTestHere can be used (see below). Construct shapes which have their control |
| // points on equal coordinates. When these are written, they can be |
| // forced to create correct 'Q' and 'T' statements using this flag. |
| // These may then be tested for import/exporting. |
| static bool bDoTestHere(true); |
| #endif // TEST_QUADRATIC_CURVES |
| |
| void SdXMLImExSvgDElement::AddPolygon( |
| drawing::PointSequence* pPoints, |
| drawing::FlagSequence* pFlags, |
| const awt::Point& rObjectPos, |
| const awt::Size& rObjectSize, |
| bool bClosed, bool bRelative) |
| { |
| DBG_ASSERT(pPoints, "Empty PointSequence handed over to SdXMLImExSvgDElement(!)"); |
| |
| sal_Int32 nCnt(pPoints->getLength()); |
| |
| // #104076# Convert to string only when at last one point included |
| if(nCnt > 0) |
| { |
| // append polygon to string |
| OUString aNewString; |
| sal_Unicode aLastCommand = ' '; |
| awt::Point* pPointArray = pPoints->getArray(); |
| |
| // are the flags used at all? If not forget about them |
| if(pFlags) |
| { |
| sal_Int32 nFlagCnt(pFlags->getLength()); |
| |
| if(nFlagCnt) |
| { |
| bool bFlagsUsed(false); |
| drawing::PolygonFlags* pFlagArray = pFlags->getArray(); |
| |
| for(sal_Int32 a(0); !bFlagsUsed && a < nFlagCnt; a++) |
| if(drawing::PolygonFlags_NORMAL != *pFlagArray++) |
| bFlagsUsed = true; |
| |
| if(!bFlagsUsed) |
| pFlags = 0L; |
| } |
| else |
| { |
| pFlags = 0L; |
| } |
| } |
| |
| // object size and ViewBox size different? |
| bool bScale(rObjectSize.Width != mrViewBox.GetWidth() |
| || rObjectSize.Height != mrViewBox.GetHeight()); |
| bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L); |
| |
| // #87202# rework of point reduction: |
| // Test for Last point same -> closed, ignore last point. Take |
| // some more circumstances in account when looking at curve segments. |
| drawing::PolygonFlags* pFlagArray = (pFlags) ? pFlags->getArray() : 0L; |
| |
| // #121090# only reduce double start/end points if polygon *is* closed |
| if(bClosed && (pPointArray->X == (pPointArray + (nCnt - 1))->X) && (pPointArray->Y == (pPointArray + (nCnt - 1))->Y)) |
| { |
| if(pFlags) |
| { |
| // point needs to be ignored if point before it is |
| // NO control point. Else the last point is needed |
| // for exporting the last segment of the curve. That means |
| // that the last and the first point will be saved double, |
| // but SVG does not support a better solution here. |
| if(nCnt >= 2 && drawing::PolygonFlags_CONTROL != *(pFlagArray + (nCnt - 2))) |
| { |
| nCnt--; |
| } |
| } |
| else |
| { |
| // no curve, ignore last point |
| nCnt--; |
| } |
| } |
| |
| // bezier poly, handle curves |
| bool bDidWriteStart(false); |
| |
| for(sal_Int32 a(0L); a < nCnt; a++) |
| { |
| if(!pFlags || drawing::PolygonFlags_CONTROL != *pFlagArray) |
| { |
| bool bDidWriteAsCurve(false); |
| |
| if(bDidWriteStart) |
| { |
| if(pFlags) |
| { |
| // real curve point, get previous to see if it's a control point |
| awt::Point* pPrevPos1; |
| drawing::PolygonFlags aPrevFlag1; |
| |
| Imp_GetPrevPos(pPrevPos1, aPrevFlag1, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 1); |
| |
| if(pPrevPos1 && drawing::PolygonFlags_CONTROL == aPrevFlag1) |
| { |
| // get previous2 to see if it's a control point, too |
| awt::Point* pPrevPos2; |
| drawing::PolygonFlags aPrevFlag2; |
| |
| Imp_GetPrevPos(pPrevPos2, aPrevFlag2, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 2); |
| |
| if(pPrevPos2 && drawing::PolygonFlags_CONTROL == aPrevFlag2) |
| { |
| // get previous3 to see if it's a curve point and if, |
| // if it is fully symmetric or not |
| awt::Point* pPrevPos3; |
| drawing::PolygonFlags aPrevFlag3; |
| |
| Imp_GetPrevPos(pPrevPos3, aPrevFlag3, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 3); |
| |
| if(pPrevPos3) |
| { |
| // prepare coordinates |
| sal_Int32 nX, nY; |
| |
| Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| // #100617# test if this curve segment may be written as |
| // a quadratic bezier |
| // That's the case if both control points are in the same place |
| // when they are prolonged to the common quadratic control point |
| // Left: P = (3P1 - P0) / 2 |
| // Right: P = (3P2 - P3) / 2 |
| bool bIsQuadratic(false); |
| const bool bEnableSaveQuadratic(false); |
| |
| sal_Int32 nPX_L(FRound((double)((3 * pPrevPos2->X) - pPrevPos3->X) / 2.0)); |
| sal_Int32 nPY_L(FRound((double)((3 * pPrevPos2->Y) - pPrevPos3->Y) / 2.0)); |
| sal_Int32 nPX_R(FRound((double)((3 * pPrevPos1->X) - pPointArray->X) / 2.0)); |
| sal_Int32 nPY_R(FRound((double)((3 * pPrevPos1->Y) - pPointArray->Y) / 2.0)); |
| sal_Int32 nDist(0); |
| |
| if(nPX_L != nPX_R) |
| { |
| nDist += abs(nPX_L - nPX_R); |
| } |
| |
| if(nPY_L != nPY_R) |
| { |
| nDist += abs(nPY_L - nPY_R); |
| } |
| |
| if(nDist <= BORDER_INTEGERS_ARE_EQUAL) |
| { |
| if(bEnableSaveQuadratic) |
| { |
| bIsQuadratic = true; |
| } |
| } |
| |
| #ifdef TEST_QUADRATIC_CURVES |
| if(bDoTestHere) |
| { |
| bIsQuadratic = false; |
| |
| if(pPrevPos1->X == pPrevPos2->X && pPrevPos1->Y == pPrevPos2->Y) |
| bIsQuadratic = true; |
| } |
| #endif // TEST_QUADRATIC_CURVES |
| |
| if(bIsQuadratic) |
| { |
| #ifdef TEST_QUADRATIC_CURVES |
| if(bDoTestHere) |
| { |
| bool bPrevPointIsSymmetric(false); |
| |
| if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3) |
| { |
| // get previous4 to see if it's a control point |
| awt::Point* pPrevPos4; |
| drawing::PolygonFlags aPrevFlag4; |
| |
| Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 4); |
| |
| if(drawing::PolygonFlags_CONTROL == aPrevFlag4) |
| { |
| // okay, prevPos3 is symmetric (c2) and prevPos4 |
| // is existing control point, the 's' statement can be used |
| bPrevPointIsSymmetric = true; |
| } |
| } |
| |
| if(bPrevPointIsSymmetric) |
| { |
| // write a shorthand/smooth quadratic curveto entry (T) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('t')) |
| aNewString += OUString(sal_Unicode('t')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('t'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('T')) |
| aNewString += OUString(sal_Unicode('T')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('T'); |
| } |
| } |
| else |
| { |
| // prepare coordinates |
| sal_Int32 nX1, nY1; |
| |
| Imp_PrepareCoorExport(nX1, nY1, pPrevPos1, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| // write a quadratic curveto entry (Q) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('q')) |
| aNewString += OUString(sal_Unicode('q')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY); |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('q'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('Q')) |
| aNewString += OUString(sal_Unicode('Q')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1); |
| Imp_PutNumberCharWithSpace(aNewString, nY1); |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('Q'); |
| } |
| } |
| } |
| else |
| { |
| #endif // TEST_QUADRATIC_CURVES |
| awt::Point aNewPoint(nPX_L, nPY_L); |
| bool bPrevPointIsSmooth(false); |
| |
| if(drawing::PolygonFlags_SMOOTH == aPrevFlag3) |
| { |
| // get previous4 to see if it's a control point |
| awt::Point* pPrevPos4; |
| drawing::PolygonFlags aPrevFlag4; |
| |
| Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 4); |
| |
| if(drawing::PolygonFlags_CONTROL == aPrevFlag4) |
| { |
| // okay, prevPos3 is smooth (c1) and prevPos4 |
| // is existing control point. Test if it's even symmetric |
| // and thus the 'T' statement may be used. |
| ::basegfx::B2DVector aVec1(pPrevPos4->X - pPrevPos3->X, pPrevPos4->Y - pPrevPos3->Y); |
| ::basegfx::B2DVector aVec2(aNewPoint.X - pPrevPos3->X, aNewPoint.Y - pPrevPos3->Y); |
| bool bSameLength(false); |
| bool bSameDirection(false); |
| |
| // get vector values |
| Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection); |
| |
| if(bSameLength && bSameDirection) |
| bPrevPointIsSmooth = true; |
| } |
| } |
| |
| if(bPrevPointIsSmooth) |
| { |
| // write a shorthand/smooth quadratic curveto entry (T) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('t')) |
| aNewString += String(sal_Unicode('t')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('t'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('T')) |
| aNewString += String(sal_Unicode('T')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('T'); |
| } |
| } |
| else |
| { |
| // prepare coordinates |
| sal_Int32 nX1, nY1; |
| |
| Imp_PrepareCoorExport(nX1, nY1, &aNewPoint, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| // write a quadratic curveto entry (Q) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('q')) |
| aNewString += String(sal_Unicode('q')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY); |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('q'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('Q')) |
| aNewString += String(sal_Unicode('Q')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1); |
| Imp_PutNumberCharWithSpace(aNewString, nY1); |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('Q'); |
| } |
| } |
| #ifdef TEST_QUADRATIC_CURVES |
| } |
| #endif // TEST_QUADRATIC_CURVES |
| } |
| else |
| { |
| bool bPrevPointIsSymmetric(false); |
| |
| if(drawing::PolygonFlags_SYMMETRIC == aPrevFlag3) |
| { |
| // get previous4 to see if it's a control point |
| awt::Point* pPrevPos4; |
| drawing::PolygonFlags aPrevFlag4; |
| |
| Imp_GetPrevPos(pPrevPos4, aPrevFlag4, bClosed, pPoints->getArray(), |
| pFlags->getArray(), a, nCnt, 4); |
| |
| if(drawing::PolygonFlags_CONTROL == aPrevFlag4) |
| { |
| // okay, prevPos3 is symmetric (c2) and prevPos4 |
| // is existing control point, the 's' statement can be used |
| bPrevPointIsSymmetric = true; |
| } |
| } |
| |
| // prepare coordinates |
| sal_Int32 nX2, nY2; |
| |
| Imp_PrepareCoorExport(nX2, nY2, pPrevPos1, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| if(bPrevPointIsSymmetric) |
| { |
| // write a shorthand/smooth curveto entry (S) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('s')) |
| aNewString += String(sal_Unicode('s')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY); |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('s'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('S')) |
| aNewString += String(sal_Unicode('S')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX2); |
| Imp_PutNumberCharWithSpace(aNewString, nY2); |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('S'); |
| } |
| } |
| else |
| { |
| // prepare coordinates |
| sal_Int32 nX1, nY1; |
| |
| Imp_PrepareCoorExport(nX1, nY1, pPrevPos2, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| // write a curveto entry (C) |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('c')) |
| aNewString += String(sal_Unicode('c')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1 - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY1 - mnLastY); |
| Imp_PutNumberCharWithSpace(aNewString, nX2 - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY2 - mnLastY); |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('c'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('C')) |
| aNewString += String(sal_Unicode('C')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX1); |
| Imp_PutNumberCharWithSpace(aNewString, nY1); |
| Imp_PutNumberCharWithSpace(aNewString, nX2); |
| Imp_PutNumberCharWithSpace(aNewString, nY2); |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('C'); |
| } |
| } |
| } |
| |
| // remember that current point IS written |
| bDidWriteAsCurve = true; |
| |
| // remember new last position |
| mnLastX = nX; |
| mnLastY = nY; |
| } |
| } |
| } |
| } |
| } |
| |
| if(!bDidWriteAsCurve) |
| { |
| // current point not yet written, prepare coordinates |
| sal_Int32 nX, nY; |
| |
| Imp_PrepareCoorExport(nX, nY, pPointArray, rObjectPos, rObjectSize, |
| mrViewBox, bScale, bTranslate); |
| |
| if(bDidWriteStart) |
| { |
| // write as normal point |
| if(mnLastX == nX) |
| { |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('v')) |
| aNewString += String(sal_Unicode('v')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('v'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('V')) |
| aNewString += String(sal_Unicode('V')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('V'); |
| } |
| } |
| else if(mnLastY == nY) |
| { |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('h')) |
| aNewString += String(sal_Unicode('h')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| |
| aLastCommand = sal_Unicode('h'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('H')) |
| aNewString += String(sal_Unicode('H')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| |
| aLastCommand = sal_Unicode('H'); |
| } |
| } |
| else |
| { |
| if(bRelative) |
| { |
| if(aLastCommand != sal_Unicode('l')) |
| aNewString += String(sal_Unicode('l')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('l'); |
| } |
| else |
| { |
| if(aLastCommand != sal_Unicode('L')) |
| aNewString += String(sal_Unicode('L')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('L'); |
| } |
| } |
| } |
| else |
| { |
| // write as start point |
| if(bRelative) |
| { |
| aNewString += String(sal_Unicode('m')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX - mnLastX); |
| Imp_PutNumberCharWithSpace(aNewString, nY - mnLastY); |
| |
| aLastCommand = sal_Unicode('l'); |
| } |
| else |
| { |
| aNewString += String(sal_Unicode('M')); |
| |
| Imp_PutNumberCharWithSpace(aNewString, nX); |
| Imp_PutNumberCharWithSpace(aNewString, nY); |
| |
| aLastCommand = sal_Unicode('L'); |
| } |
| |
| // remember start written |
| bDidWriteStart = true; |
| } |
| |
| // remember new last position |
| mnLastX = nX; |
| mnLastY = nY; |
| } |
| } |
| |
| // next point |
| pPointArray++; |
| pFlagArray++; |
| } |
| |
| // close path if closed poly |
| if(bClosed) |
| { |
| if(bRelative) |
| aNewString += String(sal_Unicode('z')); |
| else |
| aNewString += String(sal_Unicode('Z')); |
| } |
| |
| // append new string |
| msString += aNewString; |
| } |
| } |
| |
| // #100617# Linear double reader |
| double Imp_ImportDoubleAndSpaces( |
| double fRetval, const OUString& rStr, sal_Int32& rPos, |
| const sal_Int32 nLen, const SvXMLUnitConverter& rConv) |
| { |
| fRetval = Imp_GetDoubleChar(rStr, rPos, nLen, rConv, fRetval); |
| Imp_SkipSpacesAndCommas(rStr, rPos, nLen); |
| return fRetval; |
| } |
| |
| // #100617# Allow to read doubles, too. This will need to be changed to |
| // the usage of Imp_ImportDoubleAndSpaces(...). For now, this is sufficient |
| // since the interface cannot transport doubles. |
| sal_Int32 Imp_ImportNumberAndSpaces( |
| sal_Int32 nRetval, const OUString& rStr, sal_Int32& rPos, |
| const sal_Int32 nLen, const SvXMLUnitConverter& rConv) |
| { |
| nRetval = FRound(Imp_ImportDoubleAndSpaces(double(nRetval), rStr, rPos, nLen, rConv)); |
| Imp_SkipSpacesAndCommas(rStr, rPos, nLen); |
| return nRetval; |
| } |
| |
| void Imp_PrepareCoorImport(sal_Int32& nX, sal_Int32& nY, |
| const awt::Point& rObjectPos, const awt::Size& rObjectSize, |
| const SdXMLImExViewBox& rViewBox, const bool bScale, const bool bTranslate) |
| { |
| if(bTranslate) |
| { |
| nX -= rViewBox.GetX(); |
| nY -= rViewBox.GetY(); |
| } |
| |
| if(bScale && rViewBox.GetWidth() && rViewBox.GetHeight()) |
| { |
| nX = (nX * rObjectSize.Width) / rViewBox.GetWidth(); |
| nY = (nY * rObjectSize.Height) / rViewBox.GetHeight(); |
| } |
| |
| nX += rObjectPos.X; |
| nY += rObjectPos.Y; |
| } |
| |
| void Imp_AddExportPoints(sal_Int32 nX, sal_Int32 nY, |
| awt::Point* pPoints, drawing::PolygonFlags* pFlags, |
| const sal_Int32 nInnerIndex, |
| drawing::PolygonFlags eFlag) |
| { |
| if(pPoints) |
| pPoints[nInnerIndex] = awt::Point( nX, nY ); |
| |
| if(pFlags) |
| pFlags[nInnerIndex] = eFlag; |
| } |
| |
| void Imp_CalcVectorValues(::basegfx::B2DVector& aVec1, ::basegfx::B2DVector& aVec2, bool& bSameLength, bool& bSameDirection) |
| { |
| const sal_Int32 nLen1(FRound(aVec1.getLength())); |
| const sal_Int32 nLen2(FRound(aVec2.getLength())); |
| aVec1.normalize(); |
| aVec2.normalize(); |
| aVec1 += aVec2; |
| const sal_Int32 nLen3(FRound(aVec1.getLength() * ((nLen1 + nLen2) / 2.0))); |
| |
| bSameLength = (abs(nLen1 - nLen2) <= BORDER_INTEGERS_ARE_EQUAL); |
| bSameDirection = (nLen3 <= BORDER_INTEGERS_ARE_EQUAL); |
| } |
| |
| void Imp_CorrectPolygonFlag(const sal_uInt32 nInnerIndex, const awt::Point* const pInnerSequence, |
| drawing::PolygonFlags* const pInnerFlags, const sal_Int32 nX1, const sal_Int32 nY1) |
| { |
| if(nInnerIndex) |
| { |
| const awt::Point aPPrev1 = pInnerSequence[nInnerIndex - 1]; |
| |
| if(nInnerIndex > 1) |
| { |
| const awt::Point aPPrev2 = pInnerSequence[nInnerIndex - 2]; |
| const drawing::PolygonFlags aFPrev2 = pInnerFlags[nInnerIndex - 2]; |
| ::basegfx::B2DVector aVec1(aPPrev2.X - aPPrev1.X, aPPrev2.Y - aPPrev1.Y); |
| ::basegfx::B2DVector aVec2(nX1 - aPPrev1.X, nY1 - aPPrev1.Y); |
| bool bSameLength(false); |
| bool bSameDirection(false); |
| |
| // get vector values |
| Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection); |
| |
| if(drawing::PolygonFlags_CONTROL == aFPrev2) |
| { |
| // point before is a control point |
| if(bSameDirection) |
| { |
| if(bSameLength) |
| { |
| // set to PolygonFlags_SYMMETRIC |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC; |
| } |
| else |
| { |
| // set to PolygonFlags_SMOOTH |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; |
| } |
| } |
| else |
| { |
| // set to PolygonFlags_NORMAL |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; |
| } |
| } |
| else |
| { |
| // point before is a simple curve point |
| if(bSameDirection) |
| { |
| // set to PolygonFlags_SMOOTH |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; |
| } |
| else |
| { |
| // set to PolygonFlags_NORMAL |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; |
| } |
| } |
| } |
| else |
| { |
| // no point before starpoint, set type to PolygonFlags_NORMAL |
| pInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_NORMAL; |
| } |
| } |
| } |
| |
| SdXMLImExSvgDElement::SdXMLImExSvgDElement(const OUString& rNew, |
| const SdXMLImExViewBox& rViewBox, |
| const awt::Point& rObjectPos, |
| const awt::Size& rObjectSize, |
| const SvXMLUnitConverter& rConv) |
| : msString( rNew ), |
| mrViewBox( rViewBox ), |
| mbIsClosed( false ), |
| mbIsCurve( false ), |
| mnLastX( 0L ), |
| mnLastY( 0L ), |
| maPoly( 0L ), |
| maFlag( 0L ) |
| { |
| // convert string to polygon |
| const OUString aStr(msString.getStr(), msString.getLength()); |
| const sal_Int32 nLen(aStr.getLength()); |
| sal_Int32 nPos(0); |
| sal_Int32 nNumPolys(0L); |
| bool bEllipticalArc(false); |
| |
| // object size and ViewBox size different? |
| bool bScale(rObjectSize.Width != mrViewBox.GetWidth() |
| || rObjectSize.Height != mrViewBox.GetHeight()); |
| bool bTranslate(mrViewBox.GetX() != 0L || mrViewBox.GetY() != 0L); |
| |
| // first loop: count polys and get flags |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen) |
| { |
| switch(aStr[nPos++]) |
| { |
| case 'Z' : |
| case 'z' : |
| { |
| break; |
| } |
| case 'M' : |
| case 'm' : |
| { |
| nNumPolys++; |
| break; |
| } |
| case 'S' : |
| case 's' : |
| case 'C' : |
| case 'c' : |
| case 'Q' : |
| case 'q' : |
| case 'T' : |
| case 't' : |
| { |
| mbIsCurve = true; |
| break; |
| } |
| case 'L' : |
| case 'l' : |
| case 'H' : |
| case 'h' : |
| case 'V' : |
| case 'v' : |
| { |
| // normal, interpreted values. All okay. |
| break; |
| } |
| case 'A' : |
| case 'a' : |
| { |
| // Not yet interpreted value. |
| bEllipticalArc = true; |
| break; |
| } |
| } |
| } |
| |
| DBG_ASSERT(!bEllipticalArc, "XMLIMP: non-interpreted tags in svg:d element!"); |
| |
| if(nNumPolys) |
| { |
| // alloc arrays |
| maPoly.realloc(nNumPolys); |
| if(IsCurve()) |
| maFlag.realloc(nNumPolys); |
| |
| // get outer sequences |
| drawing::PointSequence* pOuterSequence = maPoly.getArray(); |
| drawing::FlagSequence* pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L; |
| |
| // prepare new loop, count |
| sal_uInt32 nPointCount(0L); |
| nPos = 0; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // #104076# reset closed flag for next to be started polygon |
| mbIsClosed = false; |
| |
| while(nPos < nLen) |
| { |
| switch(aStr[nPos]) |
| { |
| case 'z' : |
| case 'Z' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // #104076# remember closed state of current polygon |
| mbIsClosed = true; |
| |
| break; |
| } |
| case 'm' : |
| case 'M' : |
| { |
| // new poly starts, end-process current poly |
| if(nPointCount) |
| { |
| // #104076# If this partial polygon is closed, use one more point |
| // to represent that |
| if(mbIsClosed) |
| { |
| nPointCount++; |
| } |
| |
| pOuterSequence->realloc(nPointCount); |
| pOuterSequence++; |
| |
| if(pOuterFlags) |
| { |
| pOuterFlags->realloc(nPointCount); |
| pOuterFlags++; |
| } |
| |
| // reset point count for next polygon |
| nPointCount = 0L; |
| } |
| |
| // #104076# reset closed flag for next to be started polygon |
| mbIsClosed = false; |
| |
| // NO break, continue in next case |
| } |
| case 'L' : |
| case 'l' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| nPointCount++; |
| } |
| break; |
| } |
| case 'H' : |
| case 'h' : |
| case 'V' : |
| case 'v' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| nPointCount++; |
| } |
| break; |
| } |
| case 'S' : |
| case 's' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| nPointCount += 3; |
| } |
| break; |
| } |
| case 'C' : |
| case 'c' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| nPointCount += 3; |
| } |
| break; |
| } |
| |
| // #100617# quadratic beziers, supported as cubic ones |
| case 'Q' : |
| case 'q' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| |
| // use three points since quadratic is imported as cubic |
| nPointCount += 3; |
| } |
| break; |
| } |
| |
| // #100617# relative quadratic beziers, supported as cubic ones |
| case 'T' : |
| case 't' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| |
| // use three points since quadratic is imported as cubic |
| nPointCount += 3; |
| } |
| break; |
| } |
| |
| // #100617# not yet supported: elliptical arc |
| case 'A' : |
| case 'a' : |
| { |
| DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!"); |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| } |
| break; |
| } |
| |
| default: |
| { |
| nPos++; |
| DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!"); |
| break; |
| } |
| } |
| } |
| |
| // alloc last poly (when points used) |
| if(nPointCount) |
| { |
| // #104076# If this partial polygon is closed, use one more point |
| // to represent that |
| if(mbIsClosed) |
| { |
| nPointCount++; |
| } |
| |
| pOuterSequence->realloc(nPointCount); |
| pOuterSequence++; |
| |
| if(pOuterFlags) |
| { |
| pOuterFlags->realloc(nPointCount); |
| pOuterFlags++; |
| } |
| } |
| |
| // set pointers back |
| pOuterSequence = maPoly.getArray(); |
| pOuterFlags = (IsCurve()) ? maFlag.getArray() : 0L; |
| awt::Point* pNotSoInnerSequence = 0L; |
| drawing::PolygonFlags* pNotSoInnerFlags = 0L; |
| sal_uInt32 nInnerIndex(0L); |
| |
| // prepare new loop, read points |
| nPos = 0; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // #104076# reset closed flag for next to be started polygon |
| mbIsClosed = false; |
| |
| while(nPos < nLen) |
| { |
| bool bRelative(false); |
| |
| switch(aStr[nPos]) |
| { |
| case 'z' : |
| case 'Z' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| // #104076# remember closed state of current polygon |
| mbIsClosed = true; |
| |
| // closed: add first point again |
| // sal_Int32 nX(pInnerSequence[0].X); |
| // sal_Int32 nY(pInnerSequence[0].Y); |
| // Imp_AddExportPoints(nX, nY, pInnerSequence, pInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| |
| break; |
| } |
| |
| case 'm' : |
| { |
| bRelative = true; |
| } |
| case 'M' : |
| { |
| // #104076# end-process current poly |
| if(mbIsClosed) |
| { |
| if(pNotSoInnerSequence) |
| { |
| // closed: add first point again |
| sal_Int32 nX(pNotSoInnerSequence[0].X); |
| sal_Int32 nY(pNotSoInnerSequence[0].Y); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| |
| // reset closed flag for next to be started polygon |
| mbIsClosed = false; |
| } |
| |
| // next poly |
| pNotSoInnerSequence = pOuterSequence->getArray(); |
| pOuterSequence++; |
| |
| if(pOuterFlags) |
| { |
| pNotSoInnerFlags = pOuterFlags->getArray(); |
| pOuterFlags++; |
| } |
| |
| nInnerIndex = 0L; |
| |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform and add point and flag |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| break; |
| } |
| |
| case 'l' : |
| { |
| bRelative = true; |
| } |
| case 'L' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform and add point and flag |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| break; |
| } |
| |
| case 'h' : |
| { |
| bRelative = true; |
| } |
| case 'H' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(mnLastY); |
| |
| if(bRelative) |
| nX += mnLastX; |
| |
| // set last position |
| mnLastX = nX; |
| |
| // calc transform and add point and flag |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| break; |
| } |
| |
| case 'v' : |
| { |
| bRelative = true; |
| } |
| case 'V' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX(mnLastX); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| nY += mnLastY; |
| |
| // set last position |
| mnLastY = nY; |
| |
| // calc transform and add point and flag |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| break; |
| } |
| |
| case 's' : |
| { |
| bRelative = true; |
| } |
| case 'S' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX1; |
| sal_Int32 nY1; |
| sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nX2 += mnLastX; |
| nY2 += mnLastY; |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform for new points |
| Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| |
| // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC |
| // and the Point X1,Y1 can be constructed by mirroring the point before it. |
| nX1 = nX2; |
| nY1 = nY2; |
| if(nInnerIndex) |
| { |
| awt::Point aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1]; |
| |
| if(nInnerIndex > 1) |
| { |
| awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2]; |
| nX1 = aPPrev1.X -(aPPrev2.X - aPPrev1.X); |
| nY1 = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y); |
| } |
| |
| // set curve point to symmetric |
| pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SYMMETRIC; |
| } |
| |
| // add calculated control point |
| Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| |
| // add new points and set flags |
| Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); |
| } |
| break; |
| } |
| |
| case 'c' : |
| { |
| bRelative = true; |
| } |
| case 'C' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nX1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY1(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nX2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY2(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nX1 += mnLastX; |
| nY1 += mnLastY; |
| nX2 += mnLastX; |
| nY2 += mnLastY; |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform for new points |
| Imp_PrepareCoorImport(nX1, nY1, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_PrepareCoorImport(nX2, nY2, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| |
| // correct polygon flag for previous point |
| Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); |
| |
| // add new points and set flags |
| Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); |
| } |
| break; |
| } |
| |
| // #100617# quadratic beziers are imported as cubic |
| case 'q' : |
| { |
| bRelative = true; |
| } |
| case 'Q' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nXX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nYY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nXX += mnLastX; |
| nYY += mnLastY; |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform for new points |
| Imp_PrepareCoorImport(nXX, nYY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| |
| // calculate X1,X2 |
| awt::Point aPPrev1 = (nInnerIndex) ? pNotSoInnerSequence[nInnerIndex-1] : pNotSoInnerSequence[0]; |
| sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0); |
| sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0); |
| sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0); |
| sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0); |
| |
| // correct polygon flag for previous point |
| Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); |
| |
| // add new points and set flags |
| Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); |
| } |
| break; |
| } |
| |
| // #100617# relative quadratic beziers are imported as cubic |
| case 't' : |
| { |
| bRelative = true; |
| } |
| case 'T' : |
| { |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| sal_Int32 nXX; |
| sal_Int32 nYY; |
| sal_Int32 nX(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| sal_Int32 nY(Imp_ImportNumberAndSpaces(0, aStr, nPos, nLen, rConv)); |
| |
| if(bRelative) |
| { |
| nX += mnLastX; |
| nY += mnLastY; |
| } |
| |
| // set last position |
| mnLastX = nX; |
| mnLastY = nY; |
| |
| // calc transform for new points |
| Imp_PrepareCoorImport(nX, nY, rObjectPos, rObjectSize, mrViewBox, bScale, bTranslate); |
| |
| // one more thing is known: the previous real point is PolygonFlags_SYMMETRIC |
| // and the Point X1,Y1 can be constructed by mirroring the point before it. |
| nXX = nX; |
| nYY = nY; |
| awt::Point aPPrev1 = pNotSoInnerSequence[0]; |
| |
| if(nInnerIndex) |
| { |
| aPPrev1 = pNotSoInnerSequence[nInnerIndex - 1]; |
| |
| if(nInnerIndex > 1) |
| { |
| awt::Point aPPrev2 = pNotSoInnerSequence[nInnerIndex - 2]; |
| nXX = aPPrev1.X -(aPPrev2.X - aPPrev1.X); |
| nYY = aPPrev1.Y -(aPPrev2.Y - aPPrev1.Y); |
| } |
| |
| // set curve point to smooth here, since length |
| // is changed and thus only c1 can be used. |
| pNotSoInnerFlags[nInnerIndex - 1] = drawing::PolygonFlags_SMOOTH; |
| } |
| |
| // calculate X1,X2 |
| sal_Int32 nX1 = FRound((double)((nXX * 2) + aPPrev1.X) / 3.0); |
| sal_Int32 nY1 = FRound((double)((nYY * 2) + aPPrev1.Y) / 3.0); |
| sal_Int32 nX2 = FRound((double)((nXX * 2) + nX) / 3.0); |
| sal_Int32 nY2 = FRound((double)((nYY * 2) + nY) / 3.0); |
| |
| // correct polygon flag for previous point |
| Imp_CorrectPolygonFlag(nInnerIndex, pNotSoInnerSequence, pNotSoInnerFlags, nX1, nY1); |
| |
| // add new points and set flags |
| Imp_AddExportPoints(nX1, nY1, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX2, nY2, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_CONTROL); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_SMOOTH); |
| } |
| break; |
| } |
| |
| // #100617# not yet supported: elliptical arc |
| case 'A' : |
| case 'a' : |
| { |
| DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (elliptical arc)!"); |
| nPos++; |
| Imp_SkipSpaces(aStr, nPos, nLen); |
| |
| while(nPos < nLen && Imp_IsOnNumberChar(aStr, nPos)) |
| { |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipNumberAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| Imp_SkipDoubleAndSpacesAndCommas(aStr, nPos, nLen); |
| } |
| break; |
| } |
| |
| default: |
| { |
| nPos++; |
| DBG_ERROR("XMLIMP: non-interpreted tags in svg:d element (unknown)!"); |
| break; |
| } |
| } |
| } |
| |
| // #104076# end-process closed state of last poly |
| if(mbIsClosed) |
| { |
| if(pNotSoInnerSequence) |
| { |
| // closed: add first point again |
| sal_Int32 nX(pNotSoInnerSequence[0].X); |
| sal_Int32 nY(pNotSoInnerSequence[0].Y); |
| Imp_AddExportPoints(nX, nY, pNotSoInnerSequence, pNotSoInnerFlags, nInnerIndex++, drawing::PolygonFlags_NORMAL); |
| } |
| } |
| |
| // #87202# If it's a curve and it's closed the last point maybe too much |
| // and just exported since SVG does not allow special handling of same |
| // start and end point, remove this last point. |
| // Evtl. correct the last curve flags, too. |
| if(IsCurve() && IsClosed()) |
| { |
| // make one more loop over the PolyPolygon |
| pOuterSequence = maPoly.getArray(); |
| pOuterFlags = maFlag.getArray(); |
| sal_Int32 nOuterCnt(maPoly.getLength()); |
| |
| for(sal_Int32 a(0); a < nOuterCnt; a++) |
| { |
| // get Polygon pointers |
| awt::Point* pInnerSequence = pOuterSequence->getArray(); |
| drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray(); |
| sal_Int32 nInnerCnt(pOuterSequence->getLength()); |
| |
| while( nInnerCnt >= 2 |
| && ((pInnerSequence + (nInnerCnt - 2))->X == (pInnerSequence + (nInnerCnt - 1))->X) |
| && ((pInnerSequence + (nInnerCnt - 2))->Y == (pInnerSequence + (nInnerCnt - 1))->Y) |
| && drawing::PolygonFlags_CONTROL != *(pInnerFlags + (nInnerCnt - 2))) |
| { |
| // remove last point from array |
| pOuterSequence->realloc(nInnerCnt - 1); |
| pOuterFlags->realloc(nInnerCnt - 1); |
| |
| // get new pointers |
| pInnerSequence = pOuterSequence->getArray(); |
| pInnerFlags = pOuterFlags->getArray(); |
| nInnerCnt = pOuterSequence->getLength(); |
| } |
| |
| // now evtl. correct the last curve flags |
| if(nInnerCnt >= 4) |
| { |
| if( pInnerSequence->X == (pInnerSequence + (nInnerCnt - 1))->X |
| && pInnerSequence->Y == (pInnerSequence + (nInnerCnt - 1))->Y |
| && drawing::PolygonFlags_CONTROL == *(pInnerFlags + 1) |
| && drawing::PolygonFlags_CONTROL == *(pInnerFlags + (nInnerCnt - 2))) |
| { |
| awt::Point aPrev = *(pInnerSequence + (nInnerCnt - 2)); |
| awt::Point aCurr = *pInnerSequence; |
| awt::Point aNext = *(pInnerSequence + 1); |
| ::basegfx::B2DVector aVec1(aPrev.X - aCurr.X, aPrev.Y - aCurr.Y); |
| ::basegfx::B2DVector aVec2(aNext.X - aCurr.X, aNext.Y - aCurr.Y); |
| bool bSameLength(false); |
| bool bSameDirection(false); |
| |
| // get vector values |
| Imp_CalcVectorValues(aVec1, aVec2, bSameLength, bSameDirection); |
| |
| // set correct flag value |
| if(bSameDirection) |
| { |
| if(bSameLength) |
| { |
| // set to PolygonFlags_SYMMETRIC |
| *pInnerFlags = drawing::PolygonFlags_SYMMETRIC; |
| *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SYMMETRIC; |
| } |
| else |
| { |
| // set to PolygonFlags_SMOOTH |
| *pInnerFlags = drawing::PolygonFlags_SMOOTH; |
| *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_SMOOTH; |
| } |
| } |
| else |
| { |
| // set to PolygonFlags_NORMAL |
| *pInnerFlags = drawing::PolygonFlags_NORMAL; |
| *(pInnerFlags + (nInnerCnt - 1)) = drawing::PolygonFlags_NORMAL; |
| } |
| } |
| } |
| |
| // switch to next Polygon |
| pOuterSequence++; |
| pOuterFlags++; |
| } |
| } |
| } |
| } |
| |
| // eof |