diff options
Diffstat (limited to 'oox/source/drawingml/customshapepresetdata.cxx')
-rw-r--r-- | oox/source/drawingml/customshapepresetdata.cxx | 974 |
1 files changed, 974 insertions, 0 deletions
diff --git a/oox/source/drawingml/customshapepresetdata.cxx b/oox/source/drawingml/customshapepresetdata.cxx new file mode 100644 index 000000000..3215b9834 --- /dev/null +++ b/oox/source/drawingml/customshapepresetdata.cxx @@ -0,0 +1,974 @@ +/* -*- 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> +#include <o3tl/string_view.hxx> + +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, + std::string_view rValue) +{ + sal_Int32 nIndex = 0; + drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue; + do + { + OString aToken(o3tl::trim(o3tl::getToken(rValue, 0, ',', nIndex))); + static const char aNamePrefix[] = "Name = \""; + static const char aValuePrefix[] = "Value = (any) { (long) "; + if (o3tl::starts_with(aToken, aNamePrefix)) + { + OString aName = aToken.copy(strlen(aNamePrefix), + aToken.getLength() - strlen(aNamePrefix) - strlen("\"")); + aAdjustmentValue.Name = OUString::fromUtf8(aName); + } + else if (o3tl::starts_with(aToken, aValuePrefix)) + { + OString aValue = aToken.copy(strlen(aValuePrefix), + aToken.getLength() - strlen(aValuePrefix) - strlen(" }")); + aAdjustmentValue.Value <<= aValue.toInt32(); + } + else if (!o3tl::starts_with(aToken, "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, + std::string_view rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + lcl_parseAdjustmentValue( + rAdjustmentValues, + rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))); + } + } + } +} + +drawing::EnhancedCustomShapeParameterPair +lcl_parseEnhancedCustomShapeParameterPair(std::string_view 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(o3tl::starts_with(rValue, aExpectedFVPrefix)); + sal_Int32 nIndex = strlen(aExpectedFVPrefix); + aPair.First.Value + <<= static_cast<sal_uInt32>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + + static const char aExpectedFTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedFTPrefix)); + nIndex += strlen(aExpectedFTPrefix); + aPair.First.Type + = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + + static const char aExpectedSVPrefix[] = ", Second = " + "(com.sun.star.drawing.EnhancedCustomShapeParameter) { " + "Value = (any) { (long) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedSVPrefix)); + nIndex += strlen(aExpectedSVPrefix); + aPair.Second.Value + <<= static_cast<sal_uInt32>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + + static const char aExpectedSTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedSTPrefix)); + nIndex += strlen(aExpectedSTPrefix); + aPair.Second.Type + = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + return aPair; +} + +drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(std::string_view rValue) +{ + drawing::EnhancedCustomShapeSegment aSegment; + // We expect the following here: Command, Count + static const char aExpectedCommandPrefix[] = "Command = (short) "; + assert(o3tl::starts_with(rValue, aExpectedCommandPrefix)); + sal_Int32 nIndex = strlen(aExpectedCommandPrefix); + aSegment.Command + = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex))); + + static const char aExpectedCountPrefix[] = " Count = (short) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedCountPrefix)); + nIndex += strlen(aExpectedCountPrefix); + aSegment.Count = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + return aSegment; +} + +awt::Rectangle lcl_parseRectangle(std::string_view rValue) +{ + awt::Rectangle aRectangle; + // We expect the following here: X, Y, Width, Height + static const char aExpectedXPrefix[] = "X = (long) "; + assert(o3tl::starts_with(rValue, aExpectedXPrefix)); + sal_Int32 nIndex = strlen(aExpectedXPrefix); + aRectangle.X = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex)); + + static const char aExpectedYPrefix[] = " Y = (long) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedYPrefix)); + nIndex += strlen(aExpectedYPrefix); + aRectangle.Y = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex)); + + static const char aExpectedWidthPrefix[] = " Width = (long) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedWidthPrefix)); + nIndex += strlen(aExpectedWidthPrefix); + aRectangle.Width = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex)); + + static const char aExpectedHeightPrefix[] = " Height = (long) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedHeightPrefix)); + nIndex += strlen(aExpectedHeightPrefix); + aRectangle.Height = o3tl::toInt32(rValue.substr(nIndex)); + + return aRectangle; +} + +awt::Size lcl_parseSize(std::string_view rValue) +{ + awt::Size aSize; + // We expect the following here: Width, Height + static const char aExpectedWidthPrefix[] = "Width = (long) "; + assert(o3tl::starts_with(rValue, aExpectedWidthPrefix)); + sal_Int32 nIndex = strlen(aExpectedWidthPrefix); + aSize.Width = o3tl::toInt32(o3tl::getToken(rValue, 0, ',', nIndex)); + + static const char aExpectedHeightPrefix[] = " Height = (long) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedHeightPrefix)); + nIndex += strlen(aExpectedHeightPrefix); + aSize.Height = o3tl::toInt32(rValue.substr(nIndex)); + + return aSize; +} + +drawing::EnhancedCustomShapeTextFrame lcl_parseEnhancedCustomShapeTextFrame(std::string_view rValue) +{ + drawing::EnhancedCustomShapeTextFrame aTextFrame; + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" }")); + aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken); + } + else + SAL_WARN("oox", + "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } + + std::string_view aToken = rValue.substr(nStart); + static const char aExpectedPrefix[] + = "BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - 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, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "Position"; + aPropertyValue.Value <<= lcl_parseEnhancedCustomShapeParameterPair(aToken); + rHandle.push_back(aPropertyValue); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "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, std::string_view rValue, + const OUString& rName) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++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 (o3tl::starts_with(rValue.substr(nStart), aExpectedPrefix)) + { + 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(o3tl::starts_with(rValue.substr(nIndex), aExpectedVPrefix)); + nIndex += strlen(aExpectedVPrefix); + aParameter.Value <<= o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)); + + static const char aExpectedTPrefix[] = ", Type = (short) "; + assert(nIndex >= 0 && o3tl::starts_with(rValue.substr(nIndex), aExpectedTPrefix)); + nIndex += strlen(aExpectedTPrefix); + aParameter.Type + = static_cast<sal_Int16>(o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex))); + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = rName; + aPropertyValue.Value <<= aParameter; + rHandle.push_back(aPropertyValue); + } + else if (!o3tl::starts_with(rValue.substr(nStart), "Name =") + && !o3tl::starts_with(rValue.substr(nStart), "Handle =")) + SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: " + << rValue.substr(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, std::string_view rValue, + const OUString& rName) +{ + static constexpr std::string_view aPrefix = "\", Handle = (long) 0, Value = (any) { (long) "; + const sal_Int32 nStart = SAL_N_ELEMENTS("Name = \"") - 1 + rName.getLength(); + + if (rValue.substr(nStart, aPrefix.size()) == aPrefix) + { + sal_Int32 nIndex = nStart + aPrefix.size(); + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = rName; + // We only expect a Value here + aPropertyValue.Value <<= o3tl::toInt32(o3tl::getToken(rValue, 0, '}', nIndex)); + rHandle.push_back(aPropertyValue); + } + else + SAL_WARN("oox", "lcl_parseHandleRef: unexpected value: " << rValue); +} + +uno::Sequence<beans::PropertyValue> lcl_parseHandle(std::string_view rValue) +{ + std::vector<beans::PropertyValue> aRet; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + std::string_view aToken + = rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")); + if (o3tl::starts_with(aToken, "Name = \"Position\"")) + lcl_parseHandlePosition(aRet, aToken); + else if (o3tl::starts_with(aToken, "Name = \"RangeXMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeXMaximum"); + else if (o3tl::starts_with(aToken, "Name = \"RangeXMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeXMinimum"); + else if (o3tl::starts_with(aToken, "Name = \"RangeYMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeYMaximum"); + else if (o3tl::starts_with(aToken, "Name = \"RangeYMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RangeYMinimum"); + else if (o3tl::starts_with(aToken, "Name = \"RadiusRangeMaximum\"")) + lcl_parseHandleRange(aRet, aToken, "RadiusRangeMaximum"); + else if (o3tl::starts_with(aToken, "Name = \"RadiusRangeMinimum\"")) + lcl_parseHandleRange(aRet, aToken, "RadiusRangeMinimum"); + else if (o3tl::starts_with(aToken, "Name = \"RefX\"")) + lcl_parseHandleRef(aRet, aToken, "RefX"); + else if (o3tl::starts_with(aToken, "Name = \"RefY\"")) + lcl_parseHandleRef(aRet, aToken, "RefY"); + else if (o3tl::starts_with(aToken, "Name = \"RefR\"")) + lcl_parseHandleRef(aRet, aToken, "RefR"); + else if (o3tl::starts_with(aToken, "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, + std::string_view rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + uno::Sequence<beans::PropertyValue> aHandle = lcl_parseHandle( + rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },"))); + rHandles.push_back(aHandle); + } + } + } +} + +void lcl_parseEquations(std::vector<OUString>& rEquations, std::string_view rValue) +{ + bool bInString = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '"' && !bInString) + { + nStart = i; + bInString = true; + } + else if (rValue[i] == '"' && bInString) + { + bInString = false; + rEquations.push_back(OUString::fromUtf8( + rValue.substr(nStart + strlen("\""), i - nStart - strlen("\"")))); + } + } +} + +void lcl_parsePathCoordinateValues(std::vector<beans::PropertyValue>& rPath, + std::string_view rValue) +{ + std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair( + rValue.substr(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, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathCoordinateValues(rPath, aToken); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle =")) + SAL_WARN("oox", "lcl_parsePathCoordinates: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathGluePointsValues(std::vector<beans::PropertyValue>& rPath, + std::string_view rValue) +{ + std::vector<drawing::EnhancedCustomShapeParameterPair> aPairs; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aPairs.push_back(lcl_parseEnhancedCustomShapeParameterPair( + rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")))); + } + } + + beans::PropertyValue aPropertyValue; + aPropertyValue.Name = "GluePoints"; + aPropertyValue.Value <<= comphelper::containerToSequence(aPairs); + rPath.push_back(aPropertyValue); +} + +void lcl_parsePathGluePoints(std::vector<beans::PropertyValue>& rPath, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathGluePointsValues(rPath, aToken); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle =")) + SAL_WARN("oox", "lcl_parsePathGluePoints: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathSegmentValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue) +{ + std::vector<drawing::EnhancedCustomShapeSegment> aSegments; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aSegments.push_back(lcl_parseEnhancedCustomShapeSegment( + rValue.substr(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, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathSegmentValues(rPath, aToken); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle =")) + SAL_WARN("oox", "lcl_parsePathSegments: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathTextFrameValues(std::vector<beans::PropertyValue>& rPath, std::string_view rValue) +{ + std::vector<drawing::EnhancedCustomShapeTextFrame> aTextFrames; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aTextFrames.push_back(lcl_parseEnhancedCustomShapeTextFrame( + rValue.substr(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, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] + = "Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathTextFrameValues(rPath, aToken); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle =")) + SAL_WARN("oox", "lcl_parsePathTextFrames: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePathSubViewSizeValues(std::vector<beans::PropertyValue>& rPath, + std::string_view rValue) +{ + std::vector<awt::Size> aSizes; + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + aSizes.push_back(lcl_parseSize( + rValue.substr(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, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + bool bIgnore = false; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + bIgnore = true; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + bIgnore = false; + } + else if (rValue[i] == ',' && !bIgnore) + { + std::string_view aToken = rValue.substr(nStart, i - nStart); + static const char aExpectedPrefix[] = "Value = (any) { ([]com.sun.star.awt.Size) { "; + if (o3tl::starts_with(aToken, aExpectedPrefix)) + { + aToken = aToken.substr(strlen(aExpectedPrefix), + aToken.size() - strlen(aExpectedPrefix) - strlen(" } }")); + lcl_parsePathSubViewSizeValues(rPath, aToken); + } + else if (!o3tl::starts_with(aToken, "Name =") && !o3tl::starts_with(aToken, "Handle =")) + SAL_WARN("oox", "lcl_parsePathSubViewSize: unexpected token: " << aToken); + nStart = i + strlen(", "); + } + } +} + +void lcl_parsePath(std::vector<beans::PropertyValue>& rPath, std::string_view rValue) +{ + sal_Int32 nLevel = 0; + sal_Int32 nStart = 0; + for (size_t i = 0; i < rValue.size(); ++i) + { + if (rValue[i] == '{') + { + if (!nLevel) + nStart = i; + nLevel++; + } + else if (rValue[i] == '}') + { + nLevel--; + if (!nLevel) + { + std::string_view aToken + = rValue.substr(nStart + strlen("{ "), i - nStart - strlen(" },")); + if (o3tl::starts_with(aToken, "Name = \"Coordinates\"")) + lcl_parsePathCoordinates(rPath, aToken); + else if (o3tl::starts_with(aToken, "Name = \"GluePoints\"")) + lcl_parsePathGluePoints(rPath, aToken); + else if (o3tl::starts_with(aToken, "Name = \"Segments\"")) + lcl_parsePathSegments(rPath, aToken); + else if (o3tl::starts_with(aToken, "Name = \"TextFrames\"")) + lcl_parsePathTextFrames(rPath, aToken); + else if (o3tl::starts_with(aToken, "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"); + OStringBuffer aLine; + OUString aName; + bool bNotDone = aStream.ReadLine(aLine); + PropertyMap aPropertyMap; + bool bFirst = true; + while (bNotDone) + { + static const char aCommentPrefix[] = "/* "; + if (o3tl::starts_with(aLine, aCommentPrefix)) + { + if (bFirst) + bFirst = false; + else + maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap; + aName = OUString::fromUtf8(std::string_view(aLine).substr( + strlen(aCommentPrefix), + aLine.getLength() - strlen(aCommentPrefix) - strlen(" */"))); + } + else + { + if (std::string_view(aLine) == "AdjustmentValues") + { + aStream.ReadLine(aLine); + if (std::string_view(aLine) + != "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) {}") + { + std::vector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues; + static constexpr std::string_view aExpectedPrefix( + "([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { "); + assert(o3tl::starts_with(aLine, aExpectedPrefix)); + + std::string_view aValue = std::string_view(aLine).substr( + aExpectedPrefix.size(), + aLine.getLength() - aExpectedPrefix.size() - strlen(" }")); + lcl_parseAdjustmentValues(aAdjustmentValues, aValue); + aPropertyMap.setProperty(PROP_AdjustmentValues, + comphelper::containerToSequence(aAdjustmentValues)); + } + else + aPropertyMap.setProperty(PROP_AdjustmentValues, uno::Sequence<OUString>(0)); + } + else if (std::string_view(aLine) == "Equations") + { + aStream.ReadLine(aLine); + if (std::string_view(aLine) != "([]string) {}") + { + std::vector<OUString> aEquations; + static constexpr std::string_view aExpectedPrefix("([]string) { "); + assert(o3tl::starts_with(aLine, aExpectedPrefix)); + + std::string_view aValue = std::string_view(aLine).substr( + aExpectedPrefix.size(), + aLine.getLength() - aExpectedPrefix.size() - strlen(" }")); + lcl_parseEquations(aEquations, aValue); + aPropertyMap.setProperty(PROP_Equations, + comphelper::containerToSequence(aEquations)); + } + else + aPropertyMap.setProperty(PROP_Equations, uno::Sequence<OUString>(0)); + } + else if (std::string_view(aLine) == "Handles") + { + aStream.ReadLine(aLine); + if (std::string_view(aLine) != "([][]com.sun.star.beans.PropertyValue) {}") + { + std::vector<uno::Sequence<beans::PropertyValue>> aHandles; + static constexpr std::string_view aExpectedPrefix( + "([][]com.sun.star.beans.PropertyValue) { "); + assert(o3tl::starts_with(aLine, aExpectedPrefix)); + + std::string_view aValue = std::string_view(aLine).substr( + aExpectedPrefix.size(), + aLine.getLength() - aExpectedPrefix.size() - strlen(" }")); + lcl_parseHandles(aHandles, aValue); + aPropertyMap.setProperty(PROP_Handles, + comphelper::containerToSequence(aHandles)); + } + else + aPropertyMap.setProperty(PROP_Handles, uno::Sequence<OUString>(0)); + } + else if (std::string_view(aLine) == "MirroredX") + { + aStream.ReadLine(aLine); + if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false") + { + aPropertyMap.setProperty(PROP_MirroredX, std::string_view(aLine) == "true"); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected " + "MirroredX parameter"); + } + else if (std::string_view(aLine) == "MirroredY") + { + aStream.ReadLine(aLine); + if (std::string_view(aLine) == "true" || std::string_view(aLine) == "false") + { + aPropertyMap.setProperty(PROP_MirroredY, std::string_view(aLine) == "true"); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unexpected " + "MirroredY parameter"); + } + else if (std::string_view(aLine) == "Path") + { + aStream.ReadLine(aLine); + static constexpr std::string_view aExpectedPrefix( + "([]com.sun.star.beans.PropertyValue) { "); + assert(o3tl::starts_with(aLine, aExpectedPrefix)); + + std::vector<beans::PropertyValue> aPathValue; + std::string_view aValue = std::string_view(aLine).substr( + aExpectedPrefix.size(), + aLine.getLength() - aExpectedPrefix.size() - strlen(" }")); + lcl_parsePath(aPathValue, aValue); + aPropertyMap.setProperty(PROP_Path, comphelper::containerToSequence(aPathValue)); + } + else if (std::string_view(aLine) == "Type") + { + // Just ignore the line here, we already know the correct type. + aStream.ReadLine(aLine); + aPropertyMap.setProperty(PROP_Type, "ooxml-" + aName); + } + else if (std::string_view(aLine) == "ViewBox") + { + aStream.ReadLine(aLine); + static constexpr std::string_view aExpectedPrefix( + "(com.sun.star.awt.Rectangle) { "); + assert(o3tl::starts_with(aLine, aExpectedPrefix)); + + std::string_view aValue = std::string_view(aLine).substr( + aExpectedPrefix.size(), + aLine.getLength() - aExpectedPrefix.size() - strlen(" }")); + aPropertyMap.setProperty(PROP_ViewBox, lcl_parseRectangle(aValue)); + } + else + SAL_WARN("oox", "CustomShapeProperties::initializePresetDataMap: unhandled line: " + << std::string_view(aLine)); + } + bNotDone = aStream.ReadLine(aLine); + } + maPresetDataMap[TokenMap::getTokenFromUnicode(aName)] = aPropertyMap; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |