diff options
Diffstat (limited to 'xmloff/source/draw/xexptran.cxx')
-rw-r--r-- | xmloff/source/draw/xexptran.cxx | 1056 |
1 files changed, 1056 insertions, 0 deletions
diff --git a/xmloff/source/draw/xexptran.cxx b/xmloff/source/draw/xexptran.cxx new file mode 100644 index 0000000000..c3ea5a4b0f --- /dev/null +++ b/xmloff/source/draw/xexptran.cxx @@ -0,0 +1,1056 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <utility> +#include <xexptran.hxx> +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <sax/tools/converter.hxx> +#include <xmloff/xmluconv.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <basegfx/tuple/b3dtuple.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <basegfx/numeric/ftools.hxx> +#include <basegfx/matrix/b3dhommatrixtools.hxx> + +using namespace ::com::sun::star; + +// parsing help functions for simple chars +static void Imp_SkipSpaces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen) +{ + while(rPos < nLen + && ' ' == rStr[rPos]) + rPos++; +} + +static void Imp_SkipSpacesAndOpeningBraces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen) +{ + while(rPos < nLen + && (' ' == rStr[rPos] || '(' == rStr[rPos])) + rPos++; +} + +static void Imp_SkipSpacesAndCommas(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen) +{ + while(rPos < nLen + && (' ' == rStr[rPos] || ',' == rStr[rPos])) + rPos++; +} + +static void Imp_SkipSpacesAndClosingBraces(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen) +{ + while(rPos < nLen + && (' ' == rStr[rPos] || ')' == rStr[rPos])) + rPos++; +} + +// parsing help functions for integer numbers + +static bool Imp_IsOnUnitChar(std::u16string_view rStr, const sal_Int32 nPos) +{ + sal_Unicode aChar(rStr[nPos]); + + return ('a' <= aChar && 'z' >= aChar) + || ('A' <= aChar && 'Z' >= aChar) + || '%' == aChar; +} + +static double Imp_GetDoubleChar(std::u16string_view rStr, sal_Int32& rPos, const sal_Int32 nLen, + const SvXMLUnitConverter& rConv, double fRetval, bool bLookForUnits = false) +{ + sal_Unicode aChar(rStr[rPos]); + OUStringBuffer sNumberString(32); + + if('+' == aChar || '-' == aChar) + { + sNumberString.append(rStr[rPos]); + ++rPos; + aChar = rPos >= nLen ? 0 : rStr[rPos]; + } + + while(('0' <= aChar && '9' >= aChar) + || '.' == aChar) + { + sNumberString.append(rStr[rPos]); + ++rPos; + aChar = rPos >= nLen ? 0 : rStr[rPos]; + } + + if('e' == aChar || 'E' == aChar) + { + sNumberString.append(rStr[rPos]); + ++rPos; + aChar = rPos >= nLen ? 0 : rStr[rPos]; + + if('+' == aChar || '-' == aChar) + { + sNumberString.append(rStr[rPos]); + ++rPos; + aChar = rPos >= nLen ? 0 : rStr[rPos]; + } + + while('0' <= aChar && '9' >= aChar) + { + sNumberString.append(rStr[rPos]); + ++rPos; + aChar = rPos >= nLen ? 0 : rStr[rPos]; + } + } + + if(bLookForUnits) + { + Imp_SkipSpaces(rStr, rPos, nLen); + while(rPos < nLen && Imp_IsOnUnitChar(rStr, rPos)) + sNumberString.append(rStr[rPos++]); + } + + if(!sNumberString.isEmpty()) + { + if(bLookForUnits) + rConv.convertDouble(fRetval, sNumberString); + else + { + ::sax::Converter::convertDouble(fRetval, sNumberString); + } + } + + return fRetval; +} + +static void Imp_PutDoubleChar(OUString& rStr, double fValue) +{ + OUStringBuffer sStringBuffer; + ::sax::Converter::convertDouble(sStringBuffer, fValue); + rStr += sStringBuffer; +} + +static void Imp_PutDoubleChar(OUStringBuffer& rStr, const SvXMLUnitConverter& rConv, double fValue, + bool bConvertUnits = false) +{ + OUStringBuffer sStringBuffer; + + if(bConvertUnits) + rConv.convertDouble(sStringBuffer, fValue); + else + { + ::sax::Converter::convertDouble(sStringBuffer, fValue); + } + + rStr.append(sStringBuffer); +} + +// base class of all 2D transform objects + +struct ImpSdXMLExpTransObj2DBase +{ + sal_uInt16 mnType; + explicit 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 + +namespace { + +struct ImpSdXMLExpTransObj2DRotate : public ImpSdXMLExpTransObj2DBase +{ + double mfRotate; + explicit ImpSdXMLExpTransObj2DRotate(double fVal) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_ROTATE), mfRotate(fVal) {} +}; +struct ImpSdXMLExpTransObj2DScale : public ImpSdXMLExpTransObj2DBase +{ + ::basegfx::B2DTuple maScale; + explicit ImpSdXMLExpTransObj2DScale(const ::basegfx::B2DTuple& rNew) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SCALE), maScale(rNew) {} +}; +struct ImpSdXMLExpTransObj2DTranslate : public ImpSdXMLExpTransObj2DBase +{ + ::basegfx::B2DTuple maTranslate; + explicit ImpSdXMLExpTransObj2DTranslate(const ::basegfx::B2DTuple& rNew) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE), maTranslate(rNew) {} +}; +struct ImpSdXMLExpTransObj2DSkewX : public ImpSdXMLExpTransObj2DBase +{ + double mfSkewX; + explicit ImpSdXMLExpTransObj2DSkewX(double fVal) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWX), mfSkewX(fVal) {} +}; +struct ImpSdXMLExpTransObj2DSkewY : public ImpSdXMLExpTransObj2DBase +{ + double mfSkewY; + explicit ImpSdXMLExpTransObj2DSkewY(double fVal) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_SKEWY), mfSkewY(fVal) {} +}; +struct ImpSdXMLExpTransObj2DMatrix : public ImpSdXMLExpTransObj2DBase +{ + ::basegfx::B2DHomMatrix maMatrix; + explicit ImpSdXMLExpTransObj2DMatrix(::basegfx::B2DHomMatrix aNew) + : ImpSdXMLExpTransObj2DBase(IMP_SDXMLEXP_TRANSOBJ2D_MATRIX), maMatrix(std::move(aNew)) {} +}; + +} + +// add members + +void SdXMLImExTransform2D::AddRotate(double fNew) +{ + if(fNew != 0.0) + maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DRotate>(fNew)); +} + +void SdXMLImExTransform2D::AddTranslate(const ::basegfx::B2DTuple& rNew) +{ + if(!rNew.equalZero()) + maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DTranslate>(rNew)); +} + +void SdXMLImExTransform2D::AddSkewX(double fNew) +{ + if(fNew != 0.0) + maList.push_back(std::make_shared<ImpSdXMLExpTransObj2DSkewX>(fNew)); +} + +// gen string for export +const OUString& SdXMLImExTransform2D::GetExportString(const SvXMLUnitConverter& rConv) +{ + OUStringBuffer aNewString; + OUString aClosingBrace(")"); + OUString aEmptySpace(" "); + + const sal_uInt32 nCount = maList.size(); + for(sal_uInt32 a(0); a < nCount; a++) + { + ImpSdXMLExpTransObj2DBase* pObj = maList[a].get(); + switch(pObj->mnType) + { + case IMP_SDXMLEXP_TRANSOBJ2D_ROTATE : + { + aNewString.append("rotate ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DRotate*>(pObj)->mfRotate); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SCALE : + { + aNewString.append("scale ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale.getX()); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale.getY()); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE : + { + aNewString.append("translate ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate.getX(), true); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate.getY(), true); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : + { + aNewString.append("skewX ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : + { + aNewString.append("skewY ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : + { + aNewString.append("matrix ("); + + // a + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 0)); + aNewString.append(aEmptySpace); + + // b + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 0)); + aNewString.append(aEmptySpace); + + // c + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 1)); + aNewString.append(aEmptySpace); + + // d + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 1)); + aNewString.append(aEmptySpace); + + // e + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(0, 2), true); + aNewString.append(aEmptySpace); + + // f + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix.get(1, 2), true); + + aNewString.append(aClosingBrace); + break; + } + default : + { + OSL_FAIL("SdXMLImExTransform2D: impossible entry!"); + break; + } + } + + // if not the last entry, add one space to next tag + if(a + 1 != maList.size()) + { + aNewString.append(aEmptySpace); + } + } + + // fill string form OUString + msString = aNewString.makeStringAndClear(); + + return msString; +} + +// sets new string, parses it and generates entries +void SdXMLImExTransform2D::SetString(const OUString& rNew, const SvXMLUnitConverter& rConv) +{ + msString = rNew; + maList.clear(); + + if(msString.isEmpty()) + return; + + const OUString aStr = msString; + const sal_Int32 nLen(aStr.getLength()); + + static constexpr OUStringLiteral aString_rotate( u"rotate" ); + static constexpr OUStringLiteral aString_scale( u"scale" ); + static constexpr OUStringLiteral aString_translate( u"translate" ); + static constexpr OUStringLiteral aString_skewX( u"skewX" ); + static constexpr OUStringLiteral aString_skewY( u"skewY" ); + static constexpr OUStringLiteral aString_matrix( u"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(std::make_shared<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(std::make_shared<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(std::make_shared<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(std::make_shared<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(std::make_shared<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(std::make_shared<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(0); a < nCount; a++) + { + ImpSdXMLExpTransObj2DBase* pObj = maList[a].get(); + 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(static_cast<ImpSdXMLExpTransObj2DRotate*>(pObj)->mfRotate * -1.0); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SCALE : + { + const ::basegfx::B2DTuple& rScale = static_cast<ImpSdXMLExpTransObj2DScale*>(pObj)->maScale; + rFullTrans.scale(rScale.getX(), rScale.getY()); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_TRANSLATE : + { + const ::basegfx::B2DTuple& rTranslate = static_cast<ImpSdXMLExpTransObj2DTranslate*>(pObj)->maTranslate; + rFullTrans.translate(rTranslate.getX(), rTranslate.getY()); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SKEWX : + { + // For to get a mathematical correct matrix from already existing documents, + // mirror the value here. ODF spec is unclear about direction. + rFullTrans.shearX(-tan(static_cast<ImpSdXMLExpTransObj2DSkewX*>(pObj)->mfSkewX)); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_SKEWY : + { + // LibreOffice does not write skewY, OOo neither. Such files are foreign documents + // or manually set transformations. OOo had used the value as -tan(value) before + // errors were introduced, Scribus 1.5.4 uses it as -tan(value) too, MS Office does + // not shear at all. ODF spec is unclear about direction. + rFullTrans.shearY(-tan(static_cast<ImpSdXMLExpTransObj2DSkewY*>(pObj)->mfSkewY)); + break; + } + case IMP_SDXMLEXP_TRANSOBJ2D_MATRIX : + { + rFullTrans *= static_cast<ImpSdXMLExpTransObj2DMatrix*>(pObj)->maMatrix; + break; + } + default : + { + OSL_FAIL("SdXMLImExTransform2D: impossible entry!"); + break; + } + } + } +} + +// base class of all 3D transform objects + +struct ImpSdXMLExpTransObj3DBase +{ + sal_uInt16 mnType; + explicit 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 + +namespace { + +struct ImpSdXMLExpTransObj3DRotateX : public ImpSdXMLExpTransObj3DBase +{ + double mfRotateX; + explicit ImpSdXMLExpTransObj3DRotateX(double fVal) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X), mfRotateX(fVal) {} +}; +struct ImpSdXMLExpTransObj3DRotateY : public ImpSdXMLExpTransObj3DBase +{ + double mfRotateY; + explicit ImpSdXMLExpTransObj3DRotateY(double fVal) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y), mfRotateY(fVal) {} +}; +struct ImpSdXMLExpTransObj3DRotateZ : public ImpSdXMLExpTransObj3DBase +{ + double mfRotateZ; + explicit ImpSdXMLExpTransObj3DRotateZ(double fVal) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z), mfRotateZ(fVal) {} +}; +struct ImpSdXMLExpTransObj3DScale : public ImpSdXMLExpTransObj3DBase +{ + ::basegfx::B3DTuple maScale; + explicit ImpSdXMLExpTransObj3DScale(const ::basegfx::B3DTuple& rNew) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_SCALE), maScale(rNew) {} +}; +struct ImpSdXMLExpTransObj3DTranslate : public ImpSdXMLExpTransObj3DBase +{ + ::basegfx::B3DTuple maTranslate; + explicit ImpSdXMLExpTransObj3DTranslate(const ::basegfx::B3DTuple& rNew) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE), maTranslate(rNew) {} +}; +struct ImpSdXMLExpTransObj3DMatrix : public ImpSdXMLExpTransObj3DBase +{ + ::basegfx::B3DHomMatrix maMatrix; + explicit ImpSdXMLExpTransObj3DMatrix(::basegfx::B3DHomMatrix aNew) + : ImpSdXMLExpTransObj3DBase(IMP_SDXMLEXP_TRANSOBJ3D_MATRIX), maMatrix(std::move(aNew)) {} +}; + +} + +// add members + +void SdXMLImExTransform3D::AddMatrix(const ::basegfx::B3DHomMatrix& rNew) +{ + if(!rNew.isIdentity()) + maList.push_back(std::make_shared<ImpSdXMLExpTransObj3DMatrix>(rNew)); +} + +void SdXMLImExTransform3D::AddHomogenMatrix(const drawing::HomogenMatrix& xHomMat) +{ + AddMatrix(basegfx::utils::UnoHomogenMatrixToB3DHomMatrix(xHomMat)); +} + +// gen string for export +const OUString& SdXMLImExTransform3D::GetExportString(const SvXMLUnitConverter& rConv) +{ + OUStringBuffer aNewString; + OUString aClosingBrace(")"); + OUString aEmptySpace(" "); + + const sal_uInt32 nCount = maList.size(); + for(sal_uInt32 a(0); a < nCount; a++) + { + ImpSdXMLExpTransObj3DBase* pObj = maList[a].get(); + switch(pObj->mnType) + { + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X : + { + aNewString.append("rotatex ("); + Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateX*>(pObj)->mfRotateX) ); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y : + { + aNewString.append("rotatey ("); + Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateY*>(pObj)->mfRotateY) ); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z : + { + aNewString.append("rotatez ("); + Imp_PutDoubleChar(aNewString, rConv, basegfx::rad2deg( static_cast<ImpSdXMLExpTransObj3DRotateZ*>(pObj)->mfRotateZ) ); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_SCALE : + { + aNewString.append("scale ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getX()); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getY()); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale.getZ()); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE : + { + aNewString.append("translate ("); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getX(), true); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getY(), true); + aNewString.append(aEmptySpace); + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate.getZ(), true); + aNewString.append(aClosingBrace); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX : + { + aNewString.append("matrix ("); + + // a + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 0)); + aNewString.append(aEmptySpace); + + // b + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 0)); + aNewString.append(aEmptySpace); + + // c + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 0)); + aNewString.append(aEmptySpace); + + // d + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 1)); + aNewString.append(aEmptySpace); + + // e + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 1)); + aNewString.append(aEmptySpace); + + // f + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 1)); + aNewString.append(aEmptySpace); + + // g + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 2)); + aNewString.append(aEmptySpace); + + // h + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 2)); + aNewString.append(aEmptySpace); + + // i + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 2)); + aNewString.append(aEmptySpace); + + // j + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(0, 3), true); + aNewString.append(aEmptySpace); + + // k + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(1, 3), true); + aNewString.append(aEmptySpace); + + // l + Imp_PutDoubleChar(aNewString, rConv, static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix.get(2, 3), true); + + aNewString.append(aClosingBrace); + break; + } + default : + { + OSL_FAIL("SdXMLImExTransform3D: impossible entry!"); + break; + } + } + + // if not the last entry, add one space to next tag + if(a + 1 != maList.size()) + { + aNewString.append(aEmptySpace); + } + } + + // fill string form OUString + msString = aNewString.makeStringAndClear(); + + 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; + maList.clear(); + + if(msString.isEmpty()) + return; + + const OUString aStr = msString; + const sal_Int32 nLen(aStr.getLength()); + + static constexpr OUStringLiteral aString_rotatex( u"rotatex" ); + static constexpr OUStringLiteral aString_rotatey( u"rotatey" ); + static constexpr OUStringLiteral aString_rotatez( u"rotatez" ); + static constexpr OUStringLiteral aString_scale( u"scale" ); + static constexpr OUStringLiteral aString_translate( u"translate" ); + static constexpr OUStringLiteral aString_matrix( u"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(std::make_shared<ImpSdXMLExpTransObj3DRotateX>(basegfx::deg2rad(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(std::make_shared<ImpSdXMLExpTransObj3DRotateY>(basegfx::deg2rad(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(std::make_shared<ImpSdXMLExpTransObj3DRotateZ>(basegfx::deg2rad(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(std::make_shared<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(std::make_shared<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(std::make_shared<ImpSdXMLExpTransObj3DMatrix>(aValue)); + + Imp_SkipSpacesAndClosingBraces(aStr, nPos, nLen); + } + else + { + nPos++; + } + } + } +} + +bool SdXMLImExTransform3D::GetFullHomogenTransform(css::drawing::HomogenMatrix& xHomMat) +{ + ::basegfx::B3DHomMatrix aFullTransform; + GetFullTransform(aFullTransform); + + if(!aFullTransform.isIdentity()) + { + basegfx::utils::B3DHomMatrixToUnoHomogenMatrix(aFullTransform, xHomMat); + return true; + } + + return false; +} + +void SdXMLImExTransform3D::GetFullTransform(::basegfx::B3DHomMatrix& rFullTrans) +{ + rFullTrans.identity(); + + const sal_uInt32 nCount = maList.size(); + for(sal_uInt32 a(0); a < nCount; a++) + { + ImpSdXMLExpTransObj3DBase* pObj = maList[a].get(); + switch(pObj->mnType) + { + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_X : + { + rFullTrans.rotate(static_cast<ImpSdXMLExpTransObj3DRotateX*>(pObj)->mfRotateX, 0.0, 0.0); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Y : + { + rFullTrans.rotate(0.0, static_cast<ImpSdXMLExpTransObj3DRotateY*>(pObj)->mfRotateY, 0.0); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_ROTATE_Z : + { + rFullTrans.rotate(0.0, 0.0, static_cast<ImpSdXMLExpTransObj3DRotateZ*>(pObj)->mfRotateZ); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_SCALE : + { + const ::basegfx::B3DTuple& rScale = static_cast<ImpSdXMLExpTransObj3DScale*>(pObj)->maScale; + rFullTrans.scale(rScale.getX(), rScale.getY(), rScale.getZ()); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_TRANSLATE : + { + const ::basegfx::B3DTuple& rTranslate = static_cast<ImpSdXMLExpTransObj3DTranslate*>(pObj)->maTranslate; + rFullTrans.translate(rTranslate.getX(), rTranslate.getY(), rTranslate.getZ()); + break; + } + case IMP_SDXMLEXP_TRANSOBJ3D_MATRIX : + { + rFullTrans *= static_cast<ImpSdXMLExpTransObj3DMatrix*>(pObj)->maMatrix; + break; + } + default : + { + OSL_FAIL("SdXMLImExTransform3D: impossible entry!"); + break; + } + } + } +} + +SdXMLImExViewBox::SdXMLImExViewBox(double fX, double fY, double fW, double fH) +: mfX( fX ), + mfY( fY ), + mfW( fW ), + mfH( fH ) +{ +} + +// #100617# Asked vincent hardy: svg:viewBox values may be double precision. +SdXMLImExViewBox::SdXMLImExViewBox(OUString aNew, const SvXMLUnitConverter& rConv) +: msString(std::move(aNew)), + mfX( 0.0 ), + mfY( 0.0 ), + mfW( 1000.0 ), + mfH( 1000.0 ) +{ + if(msString.isEmpty()) + return; + + const OUString aStr = msString; + 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 + mfX = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfX); + + // skip spaces and commas + Imp_SkipSpacesAndCommas(aStr, nPos, nLen); + + // get mY, #100617# be prepared for doubles + mfY = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfY); + + // skip spaces and commas + Imp_SkipSpacesAndCommas(aStr, nPos, nLen); + + // get mW, #100617# be prepared for doubles + mfW = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfW); + + // skip spaces and commas + Imp_SkipSpacesAndCommas(aStr, nPos, nLen); + + // get mH, #100617# be prepared for doubles + mfH = Imp_GetDoubleChar(aStr, nPos, nLen, rConv, mfH); + +} + +const OUString& SdXMLImExViewBox::GetExportString() +{ + OUString aNewString; + OUString aEmptySpace(" "); + + Imp_PutDoubleChar(aNewString, mfX); + aNewString += aEmptySpace; + + Imp_PutDoubleChar(aNewString, mfY); + aNewString += aEmptySpace; + + Imp_PutDoubleChar(aNewString, mfW); + aNewString += aEmptySpace; + + Imp_PutDoubleChar(aNewString, mfH); + + // set new string + msString = aNewString; + + return msString; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |