[Libreoffice-commits] core.git: include/oox oox/Library_oox.mk oox/source

Miklos Vajna vmiklos at collabora.co.uk
Thu Apr 17 06:11:06 PDT 2014


 include/oox/drawingml/customshapeproperties.hxx |    3 
 oox/Library_oox.mk                              |    1 
 oox/source/drawingml/customshapepresetdata.cxx  |  743 ++++++++++++++++++++++++
 oox/source/drawingml/customshapeproperties.cxx  |    1 
 4 files changed, 748 insertions(+)

New commits:
commit d28b9e8fefa095471d1511c7948bcaf2a3473379
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Thu Apr 17 14:49:35 2014 +0200

    oox: initial customshape preset data loader
    
    CustomShapeProperties::pushToPropSet() still uses the old generated
    code, though.
    
    Change-Id: I02550bdf4ac57ef54992facd7ccd144e798be1e8

diff --git a/include/oox/drawingml/customshapeproperties.hxx b/include/oox/drawingml/customshapeproperties.hxx
index 8e237b2..29d4ba2 100644
--- a/include/oox/drawingml/customshapeproperties.hxx
+++ b/include/oox/drawingml/customshapeproperties.hxx
@@ -172,8 +172,10 @@ private:
     sal_Int32                       mnTextRotateAngle;
 
     typedef boost::unordered_map< sal_Int32, CustomShapeProvider * > PresetsMap;
+    typedef boost::unordered_map< sal_Int32, PropertyMap > PresetDataMap;
 
     static PresetsMap maPresetsMap;
+    static PresetDataMap maPresetDataMap;
     static void initializePresetsMap();
     static void initializePresetsMap1();
     static void initializePresetsMap2();
@@ -181,6 +183,7 @@ private:
     static void initializePresetsMap4();
     static void initializePresetsMap5();
     static void initializePresetsMap6();
+    static void initializePresetDataMap();
 
     sal_Int32 mnArcNum;
 };
diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index 06f0477..f27d0fa 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -138,6 +138,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
     oox/source/drawingml/customshapepresets4 \
     oox/source/drawingml/customshapepresets5 \
     oox/source/drawingml/customshapepresets6 \
+    oox/source/drawingml/customshapepresetdata \
     oox/source/drawingml/customshapeproperties \
     oox/source/drawingml/diagram/constraintlistcontext \
     oox/source/drawingml/diagram/datamodelcontext \
diff --git a/oox/source/drawingml/customshapepresetdata.cxx b/oox/source/drawingml/customshapepresetdata.cxx
new file mode 100644
index 0000000..4522c3c
--- /dev/null
+++ b/oox/source/drawingml/customshapepresetdata.cxx
@@ -0,0 +1,743 @@
+/* -*- 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 <tools/stream.hxx>
+#include <comphelper/sequenceasvector.hxx>
+
+#include "oox/drawingml/customshapeproperties.hxx"
+#include "oox/helper/helper.hxx"
+#include "oox/helper/propertymap.hxx"
+#include "oox/helper/propertyset.hxx"
+#include "oox/token/tokenmap.hxx"
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/graphic/XGraphicTransformer.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.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(comphelper::SequenceAsVector<drawing::EnhancedCustomShapeAdjustmentValue>& rAdjustmentValues, const OString& rValue)
+{
+    sal_Int32 nIndex = 0;
+    drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue;
+    do
+    {
+        OString aToken = rValue.getToken(0, ',', nIndex).trim();
+        static const OString aNamePrefix("Name = \"");
+        static const OString aValuePrefix("Value = (any) { (long) ");
+        if (aToken.startsWith(aNamePrefix))
+        {
+            OString aName = aToken.copy(aNamePrefix.getLength(), aToken.getLength() - aNamePrefix.getLength() - strlen("\""));
+            aAdjustmentValue.Name = OStringToOUString(aName, RTL_TEXTENCODING_UTF8);
+        }
+        else if (aToken.startsWith(aValuePrefix))
+        {
+            OString aValue = aToken.copy(aValuePrefix.getLength(), aToken.getLength() - aValuePrefix.getLength() - strlen(" }"));
+            aAdjustmentValue.Value = uno::makeAny(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(comphelper::SequenceAsVector<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;
+    OString aToken = rValue;
+    // We expect the followings here: First.Value, First.Type, Second.Value, Second.Type
+    static const OString aExpectedFVPrefix = "First = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
+    assert(aToken.startsWith(aExpectedFVPrefix));
+    sal_Int32 nIndex = aExpectedFVPrefix.getLength();
+    aPair.First.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
+
+    static const OString aExpectedFTPrefix = ", Type = (short) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedFTPrefix));
+    nIndex = aExpectedFTPrefix.getLength();
+    aPair.First.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
+
+    static const OString aExpectedSVPrefix = ", Second = (com.sun.star.drawing.EnhancedCustomShapeParameter) { Value = (any) { (long) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedSVPrefix));
+    nIndex = aExpectedSVPrefix.getLength();
+    aPair.Second.Value = uno::makeAny(static_cast<sal_uInt32>(aToken.getToken(0, '}', nIndex).toInt32()));
+
+    static const OString aExpectedSTPrefix = ", Type = (short) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedSTPrefix));
+    nIndex = aExpectedSTPrefix.getLength();
+    aPair.Second.Type = static_cast<sal_uInt16>(aToken.getToken(0, '}', nIndex).toInt32());
+    return aPair;
+}
+
+drawing::EnhancedCustomShapeSegment lcl_parseEnhancedCustomShapeSegment(const OString& rValue)
+{
+    drawing::EnhancedCustomShapeSegment aSegment;
+    OString aToken = rValue;
+    // We expect the followings here: Command, Count
+    static const OString aExpectedCommandPrefix = "Command = (short) ";
+    assert(aToken.startsWith(aExpectedCommandPrefix));
+    sal_Int32 nIndex = aExpectedCommandPrefix.getLength();
+    aSegment.Command = static_cast<sal_Int16>(aToken.getToken(0, ',', nIndex).toInt32());
+
+    static const OString aExpectedCountPrefix = " Count = (short) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedCountPrefix));
+    nIndex = aExpectedCountPrefix.getLength();
+    aSegment.Count = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
+    return aSegment;
+}
+
+awt::Rectangle lcl_parseRectangle(const OString& rValue)
+{
+    awt::Rectangle aRectangle;
+    OString aToken = rValue;
+    // We expect the followings here: X, Y, Width, Height
+    static const OString aExpectedXPrefix = "X = (long) ";
+    assert(aToken.startsWith(aExpectedXPrefix));
+    sal_Int32 nIndex = aExpectedXPrefix.getLength();
+    aRectangle.X = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
+
+    static const OString aExpectedYPrefix = " Y = (long) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedYPrefix));
+    nIndex = aExpectedYPrefix.getLength();
+    aRectangle.Y = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
+
+    static const OString aExpectedWidthPrefix = " Width = (long) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedWidthPrefix));
+    nIndex = aExpectedWidthPrefix.getLength();
+    aRectangle.Width = static_cast<sal_Int32>(aToken.getToken(0, ',', nIndex).toInt32());
+
+    static const OString aExpectedHeightPrefix = " Height = (long) ";
+    aToken = aToken.copy(nIndex);
+    assert(aToken.startsWith(aExpectedHeightPrefix));
+    nIndex = aExpectedHeightPrefix.getLength();
+    aRectangle.Width = static_cast<sal_Int32>(aToken.copy(nIndex).toInt32());
+
+    return aRectangle;
+}
+
+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 OString aExpectedPrefix("TopLeft = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
+                aTextFrame.TopLeft = lcl_parseEnhancedCustomShapeParameterPair(aToken);
+            }
+            else
+                SAL_WARN("oox", "lcl_parseEnhancedCustomShapeTextFrame: unexpected token: " << aToken);
+            nStart = i + strlen(", ");
+        }
+    }
+
+    OString aToken = rValue.copy(nStart, rValue.getLength() - nStart);
+    static const OString aExpectedPrefix("BottomRight = (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
+    if (aToken.startsWith(aExpectedPrefix))
+    {
+        aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - 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(comphelper::SequenceAsVector<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 OString aExpectedPrefix("Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
+
+                beans::PropertyValue aPropertyValue;
+                aPropertyValue.Name = "Position";
+                aPropertyValue.Value = uno::makeAny(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(comphelper::SequenceAsVector<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)
+        {
+            OString aToken = rValue.copy(nStart, i - nStart);
+            static const OString aExpectedPrefix("Value = (any) { (com.sun.star.drawing.EnhancedCustomShapeParameter) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                drawing::EnhancedCustomShapeParameter aParameter;
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - strlen(" } }"));
+                // We expect the followings here: Value and Type
+                static const OString aExpectedVPrefix = "Value = (any) { (long) ";
+                assert(aToken.startsWith(aExpectedVPrefix));
+                sal_Int32 nIndex = aExpectedVPrefix.getLength();
+                aParameter.Value = uno::makeAny(aToken.getToken(0, '}', nIndex).toInt32());
+
+                static const OString aExpectedTPrefix = ", Type = (short) ";
+                aToken = aToken.copy(nIndex);
+                assert(aToken.startsWith(aExpectedTPrefix));
+                nIndex = aExpectedTPrefix.getLength();
+                aParameter.Type = static_cast<sal_Int16>(aToken.getToken(0, '}', nIndex).toInt32());
+
+                beans::PropertyValue aPropertyValue;
+                aPropertyValue.Name = rName;
+                aPropertyValue.Value = uno::makeAny(aParameter);
+                rHandle.push_back(aPropertyValue);
+
+            }
+            else if (!aToken.startsWith("Name =") && !aToken.startsWith("Handle ="))
+                SAL_WARN("oox", "lcl_parseHandleRange: unexpected token: " << aToken);
+            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_parseHandleRefY(comphelper::SequenceAsVector<beans::PropertyValue>& rHandle, const OString& rValue)
+{
+    static const OString aExpectedPrefix("Name = \"RefY\", Handle = (long) 0, Value = (any) { (long) ");
+    if (rValue.startsWith(aExpectedPrefix))
+    {
+        sal_Int32 nIndex = aExpectedPrefix.getLength();
+        beans::PropertyValue aPropertyValue;
+        aPropertyValue.Name = "RefY";
+        // We only expect a Value here
+        aPropertyValue.Value = uno::makeAny(rValue.getToken(0, '}', nIndex).toInt32());
+        rHandle.push_back(aPropertyValue);
+
+    }
+    else
+        SAL_WARN("oox", "lcl_parseHandleRefY: unexpected value: " << rValue);
+}
+
+uno::Sequence<beans::PropertyValue> lcl_parseHandle(const OString& rValue)
+{
+    comphelper::SequenceAsVector<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 = \"RangeYMaximum\""))
+                    lcl_parseHandleRange(aRet, aToken, "RangeYMaximum");
+                else if (aToken.startsWith("Name = \"RangeYMinimum\""))
+                    lcl_parseHandleRange(aRet, aToken, "RangeYMinimum");
+                else if (aToken.startsWith("Name = \"RefY\""))
+                    lcl_parseHandleRefY(aRet, aToken);
+                else
+                    SAL_WARN("oox", "lcl_parseHandle: unexpected value: " << rValue);
+            }
+        }
+    }
+    return aRet.getAsConstList();
+}
+
+void lcl_parseHandles(comphelper::SequenceAsVector< 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(comphelper::SequenceAsVector<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(OStringToOUString(rValue.copy(nStart + strlen("\""), i - nStart - strlen("\"")), RTL_TEXTENCODING_UTF8));
+        }
+    }
+}
+
+void lcl_parsePathCoordinateValues(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
+{
+    comphelper::SequenceAsVector<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 = uno::makeAny(aPairs.getAsConstList());
+    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(comphelper::SequenceAsVector<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 OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeParameterPair) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - 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(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
+{
+    comphelper::SequenceAsVector<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 = uno::makeAny(aSegments.getAsConstList());
+    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(comphelper::SequenceAsVector<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 OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeSegment) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - 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(comphelper::SequenceAsVector<beans::PropertyValue>& rPath, const OString& rValue)
+{
+    comphelper::SequenceAsVector<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 = uno::makeAny(aTextFrames.getAsConstList());
+    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(comphelper::SequenceAsVector<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 OString aExpectedPrefix("Value = (any) { ([]com.sun.star.drawing.EnhancedCustomShapeTextFrame) { ");
+            if (aToken.startsWith(aExpectedPrefix))
+            {
+                aToken = aToken.copy(aExpectedPrefix.getLength(), aToken.getLength() - aExpectedPrefix.getLength() - 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_parsePath(comphelper::SequenceAsVector<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
+                    SAL_WARN("oox", "lcl_parsePath: unexpected token: " << aToken);
+            }
+        }
+    }
+}
+
+}
+
+namespace oox
+{
+namespace drawingml
+{
+
+void CustomShapeProperties::initializePresetDataMap()
+{
+    OUString aPath("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/filter/oox-drawingml-cs-presets");
+    rtl::Bootstrap::expandMacros(aPath);
+    SvFileStream aStream(aPath, STREAM_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;
+    while (bNotDone)
+    {
+        static const OString aCommentPrefix("/* ");
+        if (aLine.startsWith(aCommentPrefix))
+        {
+            aName = OStringToOUString(aLine.copy(aCommentPrefix.getLength(), aLine.getLength() - aCommentPrefix.getLength() - strlen(" */")), RTL_TEXTENCODING_UTF8);
+        }
+        else
+        {
+            if (aLine == "AdjustmentValues")
+            {
+                aStream.ReadLine(aLine);
+                OString aExpectedPrefix("([]com.sun.star.drawing.EnhancedCustomShapeAdjustmentValue) { ");
+                assert(aLine.startsWith(aExpectedPrefix));
+
+                comphelper::SequenceAsVector<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentValues;
+                OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
+                lcl_parseAdjustmentValues(aAdjustmentValues, aValue);
+                aPropertyMap.setProperty(PROP_AdjustmentValues, aAdjustmentValues.getAsConstList());
+            }
+            else if (aLine == "Equations")
+            {
+                aStream.ReadLine(aLine);
+                OString aExpectedPrefix("([]string) { ");
+                assert(aLine.startsWith(aExpectedPrefix));
+
+                comphelper::SequenceAsVector<OUString> aEquations;
+                OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
+                lcl_parseEquations(aEquations, aValue);
+                aPropertyMap.setProperty(PROP_Equations, aEquations.getAsConstList());
+            }
+            else if (aLine == "Handles")
+            {
+                aStream.ReadLine(aLine);
+                OString aExpectedPrefix("([][]com.sun.star.beans.PropertyValue) { ");
+                assert(aLine.startsWith(aExpectedPrefix));
+
+                comphelper::SequenceAsVector< uno::Sequence<beans::PropertyValue> > aHandles;
+                OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
+                lcl_parseHandles(aHandles, aValue);
+                aPropertyMap.setProperty(PROP_Handles, aHandles.getAsConstList());
+            }
+            else if (aLine == "MirroredX")
+            {
+                aStream.ReadLine(aLine);
+                if (aLine == "true" || aLine == "false")
+                {
+                    aPropertyMap.setProperty(PROP_MirroredX, sal_Bool(aLine == "true" ? sal_True : sal_False));
+                }
+                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, sal_Bool(aLine == "true" ? sal_True : sal_False));
+                }
+                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));
+
+                comphelper::SequenceAsVector<beans::PropertyValue> aPathValue;
+                OString aValue = aLine.copy(aExpectedPrefix.getLength(), aLine.getLength() - aExpectedPrefix.getLength() - strlen(" }"));
+                lcl_parsePath(aPathValue, aValue);
+                aPropertyMap.setProperty(PROP_Path, aPathValue.getAsConstList());
+            }
+            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[StaticTokenMap::get().getTokenFromUnicode(aName)] = aPropertyMap;
+}
+
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/customshapeproperties.cxx b/oox/source/drawingml/customshapeproperties.cxx
index cfaec25..229251e 100644
--- a/oox/source/drawingml/customshapeproperties.cxx
+++ b/oox/source/drawingml/customshapeproperties.cxx
@@ -91,6 +91,7 @@ sal_Int32 CustomShapeProperties::GetCustomShapeGuideValue( const std::vector< Cu
 }
 
 CustomShapeProperties::PresetsMap CustomShapeProperties::maPresetsMap;
+CustomShapeProperties::PresetDataMap CustomShapeProperties::maPresetDataMap;
 
 static OUString GetConnectorShapeType( sal_Int32 nType )
 {


More information about the Libreoffice-commits mailing list