diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /oox/source/drawingml/customshapepresetdata.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'oox/source/drawingml/customshapepresetdata.cxx')
-rw-r--r-- | oox/source/drawingml/customshapepresetdata.cxx | 891 |
1 files changed, 891 insertions, 0 deletions
diff --git a/oox/source/drawingml/customshapepresetdata.cxx b/oox/source/drawingml/customshapepresetdata.cxx new file mode 100644 index 000000000..51d547947 --- /dev/null +++ b/oox/source/drawingml/customshapepresetdata.cxx @@ -0,0 +1,891 @@ +/* -*- 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/. + */ + +#include <config_folders.h> +#include <rtl/bootstrap.hxx> +#include <sal/log.hxx> +#include <tools/stream.hxx> +#include <comphelper/sequence.hxx> + +#include <drawingml/customshapeproperties.hxx> +#include <oox/token/properties.hxx> +#include <oox/token/tokenmap.hxx> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp> +#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> + +using namespace ::com::sun::star; + +namespace +{ +// Parses a string like: Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" +void lcl_parseAdjustmentValue( + std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, + const OString& rValue) +{ + sal_Int32 nIndex = 0; + drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue; + do + { + OString aToken = rValue.getToken(0, ',', nIndex).trim(); + static const char aNamePrefix[] = "Name = \""; + static const char aValuePrefix[] = "Value = (any) { (long) "; + if (aToken.startsWith(aNamePrefix)) + { + OString aName = aToken.copy(strlen(aNamePrefix), + aToken.getLength() - strlen(aNamePrefix) - strlen("\"")); + aAdjustmentValue.Name = OUString::fromUtf8(aName); + } + else if (aToken.startsWith(aValuePrefix)) + { + OString aValue = aToken.copy(strlen(aValuePrefix), + aToken.getLength() - strlen(aValuePrefix) - strlen(" }")); + aAdjustmentValue.Value <<= aValue.toInt32(); + } + else if (!aToken.startsWith("State = ")) + SAL_WARN("oox", "lcl_parseAdjustmentValue: unexpected prefix: " << aToken); + } while (nIndex >= 0); + rAdjustmentValues.push_back(aAdjustmentValue); +} + +// Parses a string like: { Value = (any) { (long) 19098 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE, Name = "adj" }, { Value = ..., State = ..., Name = ... } +void lcl_parseAdjustmentValues( + std::vector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, + const OString& rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + lcl_parseAdjustmentValue( + rAdjustmentValues, + rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))); + } + } + } +} + +drawing::EnhancedCustomShapeParameterPair +lcl_parseEnhancedCustomShapeParameterPair(const OString& rValue) +{ + drawing::EnhancedCustomShapeParameterPair aPair; + // We expect the following here: First.Value, First.Type, Second.Value, Second.Type + static const char aExpectedFVPrefix[] + = "First = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) "; + assert(rValue.startsWith(aExpectedFVPrefix)); + sal_Int32 nIndex = strlen(aExpectedFVPrefix); + aPair.First.Value <<= static_cast<sal_uInt32>(rValue.getToken(0, '}', nIndex).toInt32()); + + static const char aExpectedFTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && rValue.match(aExpectedFTPrefix, nIndex)); + nIndex += strlen(aExpectedFTPrefix); + aPair.First.Type = static_cast<sal_uInt16>(rValue.getToken(0, '}', nIndex).toInt32()); + + static const char aExpectedSVPrefix[] = ", Second = " + "(com.sun.star.drawing.EnhancedCustomShapeParameter) { " + "Value = (any) { (long) "; + assert(nIndex >= 0 && rValue.match(aExpectedSVPrefix, nIndex)); + nIndex += strlen(aExpectedSVPrefix); + aPair.Second.Value <<= static_cast<sal_uInt32>(rValue.getToken(0, '}', nIndex).toInt32()); + + static const char aExpectedSTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && rValue.match(aExpectedSTPrefix, nIndex)); + nIndex += strlen(aExpectedSTPrefix); + aPair.Second.Type = static_cast<sal_uInt16>(rValue.getToken(0, '}', nIndex).toInt32()); + return aPair; +} + +drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(const OString& rValue) +{ + drawing::EnhancedCustomShapeSegment aSegment; + // We expect the following here: Command, Count + static const char aExpectedCommandPrefix[] = "Command = (short) "; + assert(rValue.startsWith(aExpectedCommandPrefix)); + sal_Int32 nIndex = strlen(aExpectedCommandPrefix); + aSegment.Command = static_cast<sal_Int16>(rValue.getToken(0, ',', nIndex).toInt32()); + + static const char aExpectedCountPrefix[] = " Count = (short) "; + assert(nIndex >= 0 && rValue.match(aExpectedCountPrefix, nIndex)); + nIndex += strlen(aExpectedCountPrefix); + aSegment.Count = static_cast<sal_Int16>(rValue.getToken(0, '}', nIndex).toInt32()); + return aSegment; +} + +awt::Rectangle lcl_parseRectangle(const OString& rValue) +{ + awt::Rectangle aRectangle; + // We expect the following here: X, Y, Width, Height + static const char aExpectedXPrefix[] = "X = (long) "; + assert(rValue.startsWith(aExpectedXPrefix)); + sal_Int32 nIndex = strlen(aExpectedXPrefix); + aRectangle.X = rValue.getToken(0, ',', nIndex).toInt32(); + + static const char aExpectedYPrefix[] = " Y = (long) "; + assert(nIndex >= 0 && rValue.match(aExpectedYPrefix, nIndex)); + nIndex += strlen(aExpectedYPrefix); + aRectangle.Y = rValue.getToken(0, ',', nIndex).toInt32(); + + static const char aExpectedWidthPrefix[] = " Width = (long) "; + assert(nIndex >= 0 && rValue.match(aExpectedWidthPrefix, nIndex)); + nIndex += strlen(aExpectedWidthPrefix); + aRectangle.Width = rValue.getToken(0, ',', nIndex).toInt32(); + + static const char aExpectedHeightPrefix[] = " Height = (long) "; + assert(nIndex >= 0 && rValue.match(aExpectedHeightPrefix, nIndex)); + nIndex += strlen(aExpectedHeightPrefix); + aRectangle.Height = rValue.copy(nIndex).toInt32(); + + return aRectangle; +} + +awt::Size lcl_parseSize(const OString& rValue) +{ + awt::Size aSize; + // We expect the following here: Width, Height + static const char aExpectedWidthPrefix[] = "Width = (long) "; + assert(rValue.startsWith(aExpectedWidthPrefix)); + sal_Int32 nIndex = strlen(aExpectedWidthPrefix); + aSize.Width = rValue.getToken(0, ',', nIndex).toInt32(); + + static const char aExpectedHeightPrefix[] = " Height = (long) "; + assert(nIndex >= 0 && rValue.match(aExpectedHeightPrefix, nIndex)); + nIndex += strlen(aExpectedHeightPrefix); + aSize.Height = rValue.copy(nIndex).toInt32(); + + return aSize; +} + +drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(const OString& rValue) +{ + drawing::EnhancedCustomShapeTextFrame aTextFrame; + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] + = "TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" }")); + aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken); + } + else + SAL_WARN("oox", + "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } + + OString aToken = rValue.copy(nStart); + static const char aExpectedPrefix[] + = "BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" }")); + aTextFrame.BottomRight = lcl_parseEnhancedCustomShapeParameterPair(aToken); + } + else + SAL_WARN("oox", + "lcl_parseEnhancedCustomShapeTextFrame: unexpected token at the end: " << aToken); + + return aTextFrame; +} + +// Parses a string like: Name = "Position", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +// where "{ ... }" may contain "," as well. +void lcl_parseHandlePosition(std::vector<beans::PropertyValue>& rHandle, const OString& rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }")); + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "Position"; + aPropertyValue.Value <<= lcl_parseEnhancedCustomShapeParameterPair(aToken); + rHandle.push_back(aPropertyValue); + } + else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle =")) + SAL_WARN("oox", "lcl_parseHandlePosition: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +// Parses a string like: Name = "RangeYMaximum", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +// where "{ ... }" may contain "," as well. +void lcl_parseHandleRange(std::vector<beans::PropertyValue>& rHandle, const OString& rValue, + const OUString& rName) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + static const char aExpectedPrefix[] + = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { "; + if (rValue.match(aExpectedPrefix, nStart)) + { + drawing::EnhancedCustomShapeParameter aParameter; + sal_Int32 nIndex{ nStart + static_cast<sal_Int32>(strlen(aExpectedPrefix)) }; + // We expect the following here: Value and Type + static const char aExpectedVPrefix[] = "Value = (any) { (long) "; + assert(rValue.match(aExpectedVPrefix, nIndex)); + nIndex += strlen(aExpectedVPrefix); + aParameter.Value <<= rValue.getToken(0, '}', nIndex).toInt32(); + + static const char aExpectedTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && rValue.match(aExpectedTPrefix, nIndex)); + nIndex += strlen(aExpectedTPrefix); + aParameter.Type = static_cast<sal_Int16>(rValue.getToken(0, '}', nIndex).toInt32()); + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = rName; + aPropertyValue.Value <<= aParameter; + rHandle.push_back(aPropertyValue); + } + else if (!rValue.match("Name =", nStart) && !rValue.match("Handle =", nStart)) + SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: " + << rValue.copy(nStart, i - nStart)); + nStart = i + strlen(", "); + } + } +} + +// Parses a string like: Name = "RefY", Handle = (long) 0, Value = (any) { (long) 0 }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +void lcl_parseHandleRef(std::vector<beans::PropertyValue>& rHandle, const OString& rValue, + const OUString& rName) +{ + static const char aPrefix[] = "\", Handle = (long) 0, Value = (any) { (long) "; + const sal_Int32 nCheck = SAL_N_ELEMENTS(aPrefix) - 1; + const sal_Int32 nStart = SAL_N_ELEMENTS("Name = \"") - 1 + rName.getLength(); + + if (rValue.copy(nStart, nCheck).equalsL(aPrefix, nCheck)) + { + sal_Int32 nIndex = nStart + nCheck; + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = rName; + // We only expect a Value here + aPropertyValue.Value <<= rValue.getToken(0, '}', nIndex).toInt32(); + rHandle.push_back(aPropertyValue); + } + else + SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue); +} + +uno::Sequence<beans::PropertyValue> lcl_parseHandle(const OString& rValue) +{ + std::vector<beans::PropertyValue> aRet; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")); + if (aToken.startsWith("Name = \"Position\"")) + lcl_parseHandlePosition(aRet, aToken); + else if (aToken.startsWith("Name = \"RangeXMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeXMaximum"); + else if (aToken.startsWith("Name = \"RangeXMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeXMinimum"); + else if (aToken.startsWith("Name = \"RangeYMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeYMaximum"); + else if (aToken.startsWith("Name = \"RangeYMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeYMinimum"); + else if (aToken.startsWith("Name = \"RadiusRangeMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RadiusRangeMaximum"); + else if (aToken.startsWith("Name = \"RadiusRangeMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RadiusRangeMinimum"); + else if (aToken.startsWith("Name = \"RefX\"")) + lcl_parseHandleRef(aRet, aToken, "RefX"); + else if (aToken.startsWith("Name = \"RefY\"")) + lcl_parseHandleRef(aRet, aToken, "RefY"); + else if (aToken.startsWith("Name = \"RefR\"")) + lcl_parseHandleRef(aRet, aToken, "RefR"); + else if (aToken.startsWith("Name = \"RefAngle\"")) + lcl_parseHandleRef(aRet, aToken, "RefAngle"); + else + SAL_WARN("oox", "lcl_parseHandle: unexpected token: " << aToken); + } + } + } + return comphelper::containerToSequence(aRet); +} + +void lcl_parseHandles(std::vector<uno::Sequence<beans::PropertyValue>>& rHandles, + const OString& rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle( + rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },"))); + rHandles.push_back(aHandle); + } + } + } +} + +void lcl_parseEquations(std::vector<OUString>& rEquations, const OString& rValue) +{ + bool bInString = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '"' && !bInString) + { + nStart = i; + bInString = true; + } + else if (rValue[i] == '"' && bInString) + { + bInString = false; + rEquations.push_back( + OUString::fromUtf8(rValue.copy(nStart + strlen("\""), i - nStart - strlen("\"")))); + } + } +} + +void lcl_parsePathCoordinateValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair( + rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")))); + } + } + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "Coordinates"; + aPropertyValue.Value <<= comphelper::containerToSequence(aPairs); + rPath.push_back(aPropertyValue); +} + +// Parses a string like: Name = "Coordinates", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +// where "{ ... }" may contain "," as well. +void lcl_parsePathCoordinates(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathCoordinateValues(rPath, aToken); + } + else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle =")) + SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathSegmentValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + std::vector<drawing::EnhancedCustomShapeSegment> aSegments; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aSegments.push_back(lcl_parseEnhancedCustomShapeSegment( + rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")))); + } + } + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "Segments"; + aPropertyValue.Value <<= comphelper::containerToSequence(aSegments); + rPath.push_back(aPropertyValue); +} + +// Parses a string like: Name = "Segments", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +// where "{ ... }" may contain "," as well. +void lcl_parsePathSegments(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathSegmentValues(rPath, aToken); + } + else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle =")) + SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathTextFrameValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + std::vector<drawing::EnhancedCustomShapeTextFrame> aTextFrames; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame( + rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")))); + } + } + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "TextFrames"; + aPropertyValue.Value <<= comphelper::containerToSequence(aTextFrames); + rPath.push_back(aPropertyValue); +} + +// Parses a string like: Name = "TextFrames", Handle = (long) 0, Value = (any) { ... }, State = (com.sun.star.beans.PropertyState) DIRECT_VALUE +// where "{ ... }" may contain "," as well. +void lcl_parsePathTextFrames(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathTextFrameValues(rPath, aToken); + } + else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle =")) + SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathSubViewSizeValues(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + std::vector<awt::Size> aSizes; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aSizes.push_back( + lcl_parseSize(rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")))); + } + } + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "SubViewSize"; + aPropertyValue.Value <<= comphelper::containerToSequence(aSizes); + rPath.push_back(aPropertyValue); +} + +void lcl_parsePathSubViewSize(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + OString aToken = rValue.copy(nStart, i - nStart); + static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.awt.Size) { "; + if (aToken.startsWith(aExpectedPrefix)) + { + aToken = aToken.copy(strlen(aExpectedPrefix), + aToken.getLength() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathSubViewSizeValues(rPath, aToken); + } + else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle =")) + SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePath(std::vector<beans::PropertyValue>& rPath, const OString& rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (sal_Int32 i = 0; i < rValue.getLength(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + OString aToken = rValue.copy(nStart + strlen("{ "), i - nStart - strlen(" },")); + if (aToken.startsWith("Name = \"Coordinates\"")) + lcl_parsePathCoordinates(rPath, aToken); + else if (aToken.startsWith("Name = \"Segments\"")) + lcl_parsePathSegments(rPath, aToken); + else if (aToken.startsWith("Name = \"TextFrames\"")) + lcl_parsePathTextFrames(rPath, aToken); + else if (aToken.startsWith("Name = \"SubViewSize\"")) + lcl_parsePathSubViewSize(rPath, aToken); + else + SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken); + } + } + } +} +} + +namespace oox::drawingml +{ +void CustomShapeProperties::initializePresetDataMap() +{ + OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-cs-presets"); + rtl::Bootstrap::expandMacros(aPath); + SvFileStream aStream(aPath, StreamMode::READ); + if (aStream.GetError() != ERRCODE_NONE) + SAL_WARN("oox", "failed to open oox-drawingml-cs-presets"); + OString aLine; + OUString aName; + bool bNotDone = aStream.ReadLine(aLine); + PropertyMap aPropertyMap; + bool bFirst = true; + while (bNotDone) + { + static const char aCommentPrefix[] = "/* "; + if (aLine.startsWith(aCommentPrefix)) + { + if (bFirst) + bFirst = false; + else + maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap; + aName = OUString::fromUtf8( + aLine.copy(strlen(aCommentPrefix), + aLine.getLength() - strlen(aCommentPrefix) - strlen(" */"))); + } + else + { + if (aLine == "AdjustmentValues") + { + aStream.ReadLine(aLine); + if (aLine != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}") + { + std::vector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues; + OString aExpectedPrefix( + "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { "); + assert(aLine.startsWith(aExpectedPrefix)); + + OString aValue = aLine.copy(aExpectedPrefix.getLength(), + aLine.getLength() - aExpectedPrefix.getLength() + - strlen(" }")); + lcl_parseAdjustmentValues(aAdjustmentValues, aValue); + aPropertyMap.setProperty(PROP_AdjustmentValues, + comphelper::containerToSequence(aAdjustmentValues)); + } + else + aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0)); + } + else if (aLine == "Equations") + { + aStream.ReadLine(aLine); + if (aLine != "([]string) {}") + { + std::vector<OUString> aEquations; + OString aExpectedPrefix("([]string) { "); + assert(aLine.startsWith(aExpectedPrefix)); + + OString aValue = aLine.copy(aExpectedPrefix.getLength(), + aLine.getLength() - aExpectedPrefix.getLength() + - strlen(" }")); + lcl_parseEquations(aEquations, aValue); + aPropertyMap.setProperty(PROP_Equations, + comphelper::containerToSequence(aEquations)); + } + else + aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0)); + } + else if (aLine == "Handles") + { + aStream.ReadLine(aLine); + if (aLine != "([][]com.sun.star.beans.PropertyValue) {}") + { + std::vector<uno::Sequence<beans::PropertyValue>> aHandles; + OString aExpectedPrefix("([][]com.sun.star.beans.PropertyValue) { "); + assert(aLine.startsWith(aExpectedPrefix)); + + OString aValue = aLine.copy(aExpectedPrefix.getLength(), + aLine.getLength() - aExpectedPrefix.getLength() + - strlen(" }")); + lcl_parseHandles(aHandles, aValue); + aPropertyMap.setProperty(PROP_Handles, + comphelper::containerToSequence(aHandles)); + } + else + aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0)); + } + else if (aLine == "MirroredX") + { + aStream.ReadLine(aLine); + if (aLine == "true" || aLine == "false") + { + aPropertyMap.setProperty(PROP_MirroredX, aLine == "true"); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected " + "MirroredX parameter"); + } + else if (aLine == "MirroredY") + { + aStream.ReadLine(aLine); + if (aLine == "true" || aLine == "false") + { + aPropertyMap.setProperty(PROP_MirroredY, aLine == "true"); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected " + "MirroredY parameter"); + } + else if (aLine == "Path") + { + aStream.ReadLine(aLine); + OString aExpectedPrefix("([]com.sun.star.beans.PropertyValue) { "); + assert(aLine.startsWith(aExpectedPrefix)); + + std::vector<beans::PropertyValue> aPathValue; + OString aValue + = aLine.copy(aExpectedPrefix.getLength(), + aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }")); + lcl_parsePath(aPathValue, aValue); + aPropertyMap.setProperty(PROP_Path, comphelper::containerToSequence(aPathValue)); + } + else if (aLine == "Type") + { + // Just ignore the line here, we already know the correct type. + aStream.ReadLine(aLine); + aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName); + } + else if (aLine == "ViewBox") + { + aStream.ReadLine(aLine); + OString aExpectedPrefix("(com.sun.star.awt.Rectangle) { "); + assert(aLine.startsWith(aExpectedPrefix)); + + OString aValue + = aLine.copy(aExpectedPrefix.getLength(), + aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }")); + aPropertyMap.setProperty(PROP_ViewBox, lcl_parseRectangle(aValue)); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: " + << aLine); + } + bNotDone = aStream.ReadLine(aLine); + } + maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |