[Libreoffice-commits] core.git: Branch 'libreoffice-6-1' - oox/inc oox/Library_oox.mk oox/source sd/qa

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Aug 20 08:13:20 UTC 2018


 oox/Library_oox.mk                                 |    1 
 oox/inc/drawingml/presetgeometrynames.hxx          |   23 ++
 oox/inc/drawingml/textbodycontext.hxx              |    2 
 oox/inc/drawingml/textbodyproperties.hxx           |    1 
 oox/inc/drawingml/textbodypropertiescontext.hxx    |    5 
 oox/source/drawingml/presetgeometrynames.cxx       |  108 ++++++++++++
 oox/source/drawingml/shape.cxx                     |  185 +++++++++++++++++++++
 oox/source/drawingml/shapecontext.cxx              |    4 
 oox/source/drawingml/textbodycontext.cxx           |   12 +
 oox/source/drawingml/textbodyproperties.cxx        |    1 
 oox/source/drawingml/textbodypropertiescontext.cxx |   32 +++
 oox/source/ppt/pptshapecontext.cxx                 |    2 
 sd/qa/unit/data/pptx/tdf116350-texteffects.pptx    |binary
 sd/qa/unit/export-tests-ooxml2.cxx                 |   50 +++++
 14 files changed, 421 insertions(+), 5 deletions(-)

New commits:
commit b56857dbd21083f5d41eaf4c0f08db1977cf8d2e
Author:     Szymon Kłos <szymon.klos at collabora.com>
AuthorDate: Fri Jul 20 17:21:43 2018 +0200
Commit:     Andras Timar <andras.timar at collabora.com>
CommitDate: Mon Aug 20 10:12:58 2018 +0200

    tdf#116350 Import preset text geometry (text effects)
    
    "Font effect" implementation, instead of normal
    text, content is converted to "fontwork".
    
    Change-Id: I5d02c7faedb66a4b919e64ae1b830bffb69984c1
    Reviewed-on: https://gerrit.libreoffice.org/58358
    Tested-by: Jenkins
    Reviewed-by: Szymon Kłos <szymon.klos at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/58838
    Reviewed-by: Andras Timar <andras.timar at collabora.com>

diff --git a/oox/Library_oox.mk b/oox/Library_oox.mk
index a21157be131f..e917a9b866d3 100644
--- a/oox/Library_oox.mk
+++ b/oox/Library_oox.mk
@@ -159,6 +159,7 @@ $(eval $(call gb_Library_add_exception_objects,oox,\
     oox/source/drawingml/linepropertiescontext \
     oox/source/drawingml/lineproperties \
     oox/source/drawingml/objectdefaultcontext \
+    oox/source/drawingml/presetgeometrynames \
     oox/source/drawingml/scene3dcontext \
     oox/source/drawingml/shapecontext \
     oox/source/drawingml/shape \
diff --git a/oox/inc/drawingml/presetgeometrynames.hxx b/oox/inc/drawingml/presetgeometrynames.hxx
new file mode 100644
index 000000000000..51721e41febd
--- /dev/null
+++ b/oox/inc/drawingml/presetgeometrynames.hxx
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#ifndef INCLUDED_OOX_DRAWINGML_PRESETGEOMETRYNAMES_HXX
+#define INCLUDED_OOX_DRAWINGML_PRESETGEOMETRYNAMES_HXX
+
+#include <rtl/ustring.hxx>
+#include <oox/dllapi.h>
+
+namespace PresetGeometryTypeNames
+{
+OOX_DLLPUBLIC OUString GetFontworkType(const OUString& rMsoType);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/oox/inc/drawingml/textbodycontext.hxx b/oox/inc/drawingml/textbodycontext.hxx
index a3439105493a..39ae7b8a1b59 100644
--- a/oox/inc/drawingml/textbodycontext.hxx
+++ b/oox/inc/drawingml/textbodycontext.hxx
@@ -32,11 +32,13 @@ class TextBodyContext final : public ::oox::core::ContextHandler2
 {
 public:
     TextBodyContext( ::oox::core::ContextHandler2Helper const & rParent, TextBody& rTextBody );
+    TextBodyContext( ::oox::core::ContextHandler2Helper const & rParent, ShapePtr pShapePtr );
 
     virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) override;
 
 private:
     TextBody&           mrTextBody;
+    ShapePtr            mpShapePtr;
 };
 
 // CT_RegularTextRun
diff --git a/oox/inc/drawingml/textbodyproperties.hxx b/oox/inc/drawingml/textbodyproperties.hxx
index bcb75546a688..62ee3190ae58 100644
--- a/oox/inc/drawingml/textbodyproperties.hxx
+++ b/oox/inc/drawingml/textbodyproperties.hxx
@@ -41,6 +41,7 @@ struct TextBodyProperties
     boost::optional< sal_Int32 >                    moTextOffLower;
     boost::optional< sal_Int32 >                    moTextOffRight;
     css::drawing::TextVerticalAdjust                meVA;
+    OUString                                        msPrst;
 
     explicit            TextBodyProperties();
 
diff --git a/oox/inc/drawingml/textbodypropertiescontext.hxx b/oox/inc/drawingml/textbodypropertiescontext.hxx
index 0ec5fe455185..b6305866e014 100644
--- a/oox/inc/drawingml/textbodypropertiescontext.hxx
+++ b/oox/inc/drawingml/textbodypropertiescontext.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_OOX_DRAWINGML_TEXTBODYPROPERTIESCONTEXT_HXX
 
 #include <oox/core/contexthandler2.hxx>
+#include <oox/drawingml/drawingmltypes.hxx>
 
 namespace oox { namespace drawingml {
 
@@ -33,10 +34,14 @@ public:
              const ::oox::AttributeList& rAttributes,
              TextBodyProperties& rTextBodyProp );
 
+    TextBodyPropertiesContext( ::oox::core::ContextHandler2Helper const & rParent,
+             const ::oox::AttributeList& rAttributes, ShapePtr pShapePtr );
+
     virtual ::oox::core::ContextHandlerRef onCreateContext( ::sal_Int32 Element, const ::oox::AttributeList& rAttribs ) override;
 
 private:
     TextBodyProperties& mrTextBodyProp;
+    ShapePtr mpShapePtr;
 };
 
 } }
diff --git a/oox/source/drawingml/presetgeometrynames.cxx b/oox/source/drawingml/presetgeometrynames.cxx
new file mode 100644
index 000000000000..4939cfcf0a3f
--- /dev/null
+++ b/oox/source/drawingml/presetgeometrynames.cxx
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <osl/mutex.hxx>
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <unordered_map>
+#include <cstring>
+#include <drawingml/presetgeometrynames.hxx>
+#include <memory>
+
+namespace
+{
+typedef std::unordered_map<const char*, const char*, rtl::CStringHash, rtl::CStringEqual>
+    PresetGeometryHashMap;
+
+static PresetGeometryHashMap* pHashMap = nullptr;
+::osl::Mutex& getHashMapMutex()
+{
+    static osl::Mutex s_aHashMapProtection;
+    return s_aHashMapProtection;
+}
+
+struct PresetGeometryName
+{
+    const char* pMsoName;
+    const char* pFontworkType;
+};
+
+static const PresetGeometryName pPresetGeometryNameArray[]
+    = { { "textNoShape", "" },
+        { "textPlain", "fontwork-plain-text" },
+        { "textStop", "fontwork-stop" },
+        { "textTriangle", "fontwork-triangle-up" },
+        { "textTriangleInverted", "fontwork-triangle-down" },
+        { "textChevron", "fontwork-chevron-up" },
+        { "textChevronInverted", "fontwork-chevron-down" },
+        { "textRingInside", "mso-spt142" },
+        { "textRingOutside", "mso-spt143" },
+        { "textArchUp", "fontwork-arch-up-curve" },
+        { "textArchDown", "fontwork-arch-down-curve" },
+        { "textCircle", "fontwork-circle-curve" },
+        { "textButton", "fontwork-open-circle-curve" },
+        { "textArchUpPour", "fontwork-arch-up-pour" },
+        { "textArchDownPour", "fontwork-arch-down-pour" },
+        { "textCirclePour", "fontwork-circle-pour" },
+        { "textButtonPour", "fontwork-open-circle-pour" },
+        { "textCurveUp", "fontwork-curve-up" },
+        { "textCurveDown", "fontwork-curve-down" },
+        { "textCanUp", "mso-spt174" },
+        { "textCanDown", "mso-spt175" },
+        { "textWave1", "fontwork-wave" },
+        { "textWave2", "mso-spt157" },
+        { "textDoubleWave1", "mso-spt158" },
+        { "textWave4", "mso-spt159" },
+        { "textInflate", "fontwork-inflate" },
+        { "textDeflate", "fontwork-inflate" },
+        { "textInflateBottom", "mso-spt162" },
+        { "textDeflateBottom", "mso-spt163" },
+        { "textInflateTop", "mso-spt163" },
+        { "textDeflateTop", "mso-spt165" },
+        { "textDeflateInflate", "mso-spt166" },
+        { "textDeflateInflateDeflate", "mso-spt167" },
+        { "textFadeRight", "fontwork-fade-right" },
+        { "textFadeLeft", "fontwork-fade-left" },
+        { "textFadeUp", "fontwork-fade-up" },
+        { "textFadeDown", "fontwork-fade-down" },
+        { "textSlantUp", "fontwork-slant-up" },
+        { "textSlantDown", "fontwork-slant-down" },
+        { "textCascadeUp", "fontwork-fade-up-and-right" },
+        { "textCascadeDown", "fontwork-fade-up-and-left" } };
+}
+
+OUString PresetGeometryTypeNames::GetFontworkType(const OUString& rMsoType)
+{
+    if (!pHashMap)
+    { // init hash map
+        ::osl::MutexGuard aGuard(getHashMapMutex());
+        if (!pHashMap)
+        {
+            PresetGeometryHashMap* pH = new PresetGeometryHashMap;
+            const PresetGeometryName* pPtr = pPresetGeometryNameArray;
+            const PresetGeometryName* pEnd = pPtr + SAL_N_ELEMENTS(pPresetGeometryNameArray);
+            for (; pPtr < pEnd; pPtr++)
+                (*pH)[pPtr->pMsoName] = pPtr->pFontworkType;
+            pHashMap = pH;
+        }
+    }
+    const char* pRetValue = "";
+    int i, nLen = rMsoType.getLength();
+    std::unique_ptr<char[]> pBuf(new char[nLen + 1]);
+    for (i = 0; i < nLen; i++)
+        pBuf[i] = static_cast<char>(rMsoType[i]);
+    pBuf[i] = 0;
+    PresetGeometryHashMap::const_iterator aHashIter(pHashMap->find(pBuf.get()));
+    if (aHashIter != pHashMap->end())
+        pRetValue = (*aHashIter).second;
+
+    return OUString(pRetValue, strlen(pRetValue), RTL_TEXTENCODING_ASCII_US);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index 3aac4273fc4c..2a28ea06d0ec 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -24,6 +24,7 @@
 #include <drawingml/graphicproperties.hxx>
 #include <drawingml/scene3dcontext.hxx>
 #include <drawingml/lineproperties.hxx>
+#include <drawingml/presetgeometrynames.hxx>
 #include "effectproperties.hxx"
 #include <oox/drawingml/shapepropertymap.hxx>
 #include <drawingml/textbody.hxx>
@@ -56,6 +57,7 @@
 #include <editeng/unoprnms.hxx>
 #include <com/sun/star/awt/Size.hpp>
 #include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
 #include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/container/XNamed.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
@@ -67,6 +69,8 @@
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
 #include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
 #include <com/sun/star/text/XText.hpp>
 #include <com/sun/star/table/BorderLine2.hpp>
@@ -87,6 +91,8 @@
 #include <vcl/graph.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+#include <svx/unoshape.hxx>
 
 #include <vcl/wmf.hxx>
 
@@ -394,6 +400,172 @@ void Shape::addChildren(
     }
 }
 
+static inline void lcl_resetPropertyValue( std::vector<beans::PropertyValue>& rPropVec, const OUString& rName )
+{
+    auto aIterator = std::find_if( rPropVec.begin(), rPropVec.end(),
+        [rName]( const beans::PropertyValue& rValue ) { return rValue.Name == rName; } );
+
+    if (aIterator != rPropVec.end())
+        rPropVec.erase( aIterator );
+}
+
+static inline void lcl_setPropertyValue( std::vector<beans::PropertyValue>& rPropVec,
+                           const OUString& rName,
+                           const beans::PropertyValue& rPropertyValue )
+{
+    auto aIterator = std::find_if(
+        rPropVec.begin(), rPropVec.end(),
+        [rName]( const beans::PropertyValue& rValue ) { return rValue.Name == rName; } );
+
+    if (aIterator != rPropVec.end())
+        rPropVec.erase( aIterator );
+
+    rPropVec.push_back( rPropertyValue );
+}
+
+static inline SdrTextHorzAdjust lcl_convertAdjust( ParagraphAdjust eAdjust )
+{
+    if (eAdjust == ParagraphAdjust_LEFT)
+        return SDRTEXTHORZADJUST_LEFT;
+    else if (eAdjust == ParagraphAdjust_RIGHT)
+        return SDRTEXTHORZADJUST_RIGHT;
+    else if (eAdjust == ParagraphAdjust_CENTER)
+        return SDRTEXTHORZADJUST_CENTER;
+    return SDRTEXTHORZADJUST_LEFT;
+}
+
+static inline void lcl_createPresetShape( uno::Reference<drawing::XShape>& xShape,
+                                   const OUString& rClass,
+                                   const CustomShapePropertiesPtr pCustomShapePropertiesPtr,
+                                   const TextBodyPtr pTextBody,
+                                   const GraphicHelper& rGraphicHelper )
+{
+    if (!xShape.is() || !pCustomShapePropertiesPtr || !pTextBody)
+        return;
+
+    uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter( xShape,
+                                                                       uno::UNO_QUERY );
+
+    if (!xDefaulter.is() || rClass.isEmpty())
+        return;
+
+    Reference<XPropertySet> xSet( xShape, UNO_QUERY );
+    if (!xSet.is())
+        return;
+
+    auto aGdList = pCustomShapePropertiesPtr->getAdjustmentGuideList();
+    Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustment(
+        aGdList.size() ? aGdList.size() : 1 );
+
+    int nIndex = 0;
+    for (auto& aEntry : aGdList)
+    {
+        double fAngle = NormAngle360( aEntry.maFormula.toDouble() / -600.0 );
+        fAngle = 360.0 - fAngle / 100.0;
+
+        aAdjustment[nIndex].Value <<= fAngle;
+        aAdjustment[nIndex++].State = css::beans::PropertyState_DIRECT_VALUE;
+    }
+
+    if (!aGdList.size())
+    {
+        // Default angle
+        double fAngle = 0;
+        if (rClass == "fontwork-arch-up-curve")
+            fAngle = 180;
+
+        aAdjustment[0].Value <<= fAngle;
+        aAdjustment[0].State = css::beans::PropertyState_DIRECT_VALUE;
+    }
+
+    // Set properties
+    xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny( false ) );
+    xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny( false ) );
+    xSet->setPropertyValue( UNO_NAME_FILLSTYLE, uno::makeAny( drawing::FillStyle_SOLID ) );
+
+    const TextParagraphVector& rParagraphs = pTextBody->getParagraphs();
+    if (rParagraphs.size() && rParagraphs[0]->getRuns().size())
+    {
+        std::shared_ptr<TextParagraph> pParagraph = rParagraphs[0];
+        std::shared_ptr<TextRun> pRun = pParagraph->getRuns()[0];
+        TextCharacterProperties& pProperties = pRun->getTextCharacterProperties();
+
+        if (pProperties.moBold.has() && pProperties.moBold.get())
+        {
+            xSet->setPropertyValue( UNO_NAME_CHAR_WEIGHT, uno::makeAny( css::awt::FontWeight::BOLD ) );
+        }
+        if (pProperties.moItalic.has() && pProperties.moItalic.get())
+        {
+            xSet->setPropertyValue( UNO_NAME_CHAR_POSTURE, uno::makeAny( css::awt::FontSlant::FontSlant_ITALIC ) );
+        }
+        if (pProperties.moHeight.has())
+        {
+            sal_Int32 nHeight = pProperties.moHeight.get() / 100;
+            xSet->setPropertyValue( UNO_NAME_CHAR_HEIGHT, uno::makeAny( nHeight ) );
+        }
+        if (pProperties.maFillProperties.maFillColor.isUsed())
+        {
+            const sal_Int32 aFillColor = static_cast<sal_Int32>(
+                pProperties.maFillProperties.maFillColor.getColor( rGraphicHelper ).GetRGBColor() );
+            xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( aFillColor ) );
+        }
+        else
+        {
+            // Set default color
+            xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( COL_BLACK ) );
+        }
+        {
+            ParagraphAdjust eAdjust = ParagraphAdjust_LEFT;
+            if (pParagraph->getProperties().getParaAdjust())
+                eAdjust = pParagraph->getProperties().getParaAdjust().get();
+            xSet->setPropertyValue( "ParaAdjust", uno::makeAny( eAdjust ) );
+            SvxShape* pShape = SvxShape::getImplementation( xShape );
+            SdrTextHorzAdjust eHorzAdjust = lcl_convertAdjust( eAdjust );
+            pShape->GetSdrObject()->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust ) );
+        }
+    }
+
+    // Apply preset shape
+    xDefaulter->createCustomShapeDefaults( rClass );
+
+    auto aGeomPropSeq = xSet->getPropertyValue( "CustomShapeGeometry" )
+                            .get<uno::Sequence<beans::PropertyValue>>();
+    auto aGeomPropVec
+        = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>(
+            aGeomPropSeq );
+
+    // Reset old properties
+    const OUString sCoordinateSize( "CoordinateSize" );
+    const OUString sEquations( "Equations" );
+    const OUString sPath( "Path" );
+    const OUString sTextPath( "TextPath" );
+    const OUString sAdjustmentValues( "AdjustmentValues" );
+
+    lcl_resetPropertyValue( aGeomPropVec, sCoordinateSize );
+    lcl_resetPropertyValue( aGeomPropVec, sEquations );
+    lcl_resetPropertyValue( aGeomPropVec, sPath );
+
+    // Apply geometry properties
+    uno::Sequence<beans::PropertyValue> aPropertyValues(
+        comphelper::InitPropertySequence(
+            { { sTextPath, uno::makeAny( true ) },
+                { "TextPathMode",
+                uno::Any( drawing::EnhancedCustomShapeTextPathMode_PATH ) },
+                { "ScaleX", uno::Any( false ) } } ) );
+
+    lcl_setPropertyValue( aGeomPropVec, sTextPath,
+        comphelper::makePropertyValue( sTextPath, aPropertyValues ) );
+
+    if ( rClass == "fontwork-arch-up-curve" || rClass == "fontwork-circle-curve"
+        || rClass == "fontwork-arch-down-curve" || rClass == "fontwork-open-circle-curve" )
+        lcl_setPropertyValue( aGeomPropVec, sAdjustmentValues,
+            comphelper::makePropertyValue( sAdjustmentValues, aAdjustment ) );
+
+    xSet->setPropertyValue(
+        "CustomShapeGeometry",
+        uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
+}
+
 Reference< XShape > const & Shape::createAndInsert(
         ::oox::core::XmlFilterBase& rFilterBase,
         const OUString& rServiceName,
@@ -1127,6 +1299,19 @@ Reference< XShape > const & Shape::createAndInsert(
             SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName << "'");
             SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName << "'");
             mpCustomShapePropertiesPtr->pushToPropSet( xSet, mxShape, maSize );
+
+            if (mpTextBody)
+            {
+                bool bIsPresetShape = !mpTextBody->getTextProperties().msPrst.isEmpty();
+                if (bIsPresetShape)
+                {
+                    OUString sClass;
+                    const OUString sPresetType = mpTextBody->getTextProperties().msPrst;
+                    sClass = PresetGeometryTypeNames::GetFontworkType( sPresetType );
+
+                    lcl_createPresetShape( mxShape, sClass, mpCustomShapePropertiesPtr, mpTextBody, rGraphicHelper );
+                }
+            }
         }
         else if( getTextBody() )
             getTextBody()->getTextProperties().pushVertSimulation();
diff --git a/oox/source/drawingml/shapecontext.cxx b/oox/source/drawingml/shapecontext.cxx
index 21cc6b329ed3..3abe2dee0adf 100644
--- a/oox/source/drawingml/shapecontext.cxx
+++ b/oox/source/drawingml/shapecontext.cxx
@@ -96,7 +96,7 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 aElementToken, const
     {
         if (!mpShapePtr->getTextBody())
             mpShapePtr->setTextBody( std::make_shared<TextBody>() );
-        return new TextBodyContext( *this, *mpShapePtr->getTextBody() );
+        return new TextBodyContext( *this, mpShapePtr );
     }
     case XML_txXfrm:
     {
@@ -112,7 +112,7 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 aElementToken, const
     case XML_bodyPr:
         if (!mpShapePtr->getTextBody())
             mpShapePtr->setTextBody( std::make_shared<TextBody>() );
-        return new TextBodyPropertiesContext( *this, rAttribs, mpShapePtr->getTextBody()->getTextProperties() );
+        return new TextBodyPropertiesContext( *this, rAttribs, mpShapePtr );
         break;
     case XML_txbx:
         break;
diff --git a/oox/source/drawingml/textbodycontext.cxx b/oox/source/drawingml/textbodycontext.cxx
index ea985f6b78a0..84cf4d4b071b 100644
--- a/oox/source/drawingml/textbodycontext.cxx
+++ b/oox/source/drawingml/textbodycontext.cxx
@@ -25,6 +25,7 @@
 #include <drawingml/textliststylecontext.hxx>
 #include <drawingml/textfield.hxx>
 #include <drawingml/textfieldcontext.hxx>
+#include <oox/drawingml/shape.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/tokens.hxx>
 
@@ -161,12 +162,21 @@ TextBodyContext::TextBodyContext( ContextHandler2Helper const & rParent, TextBod
 {
 }
 
+TextBodyContext::TextBodyContext( ContextHandler2Helper const & rParent, ShapePtr pShapePtr )
+: TextBodyContext( rParent, *pShapePtr->getTextBody() )
+{
+    mpShapePtr = pShapePtr;
+}
+
 ContextHandlerRef TextBodyContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
 {
     switch( aElementToken )
     {
         case A_TOKEN( bodyPr ):     // CT_TextBodyPropertyBag
-            return new TextBodyPropertiesContext( *this, rAttribs, mrTextBody.getTextProperties() );
+            if ( mpShapePtr )
+                return new TextBodyPropertiesContext( *this, rAttribs, mpShapePtr );
+            else
+                return new TextBodyPropertiesContext( *this, rAttribs, mrTextBody.getTextProperties() );
         case A_TOKEN( lstStyle ):   // CT_TextListStyle
             return new TextListStyleContext( *this, mrTextBody.getTextListStyle() );
         case A_TOKEN( p ):          // CT_TextParagraph
diff --git a/oox/source/drawingml/textbodyproperties.cxx b/oox/source/drawingml/textbodyproperties.cxx
index 71f8c8c3f1bd..5998c429b494 100644
--- a/oox/source/drawingml/textbodyproperties.cxx
+++ b/oox/source/drawingml/textbodyproperties.cxx
@@ -33,6 +33,7 @@ namespace drawingml {
 TextBodyProperties::TextBodyProperties()
     : mbAnchorCtr(false)
     , meVA( TextVerticalAdjust_TOP )
+    , msPrst()
 {
 }
 
diff --git a/oox/source/drawingml/textbodypropertiescontext.cxx b/oox/source/drawingml/textbodypropertiescontext.cxx
index 944ada853ef1..6de4a0764cbd 100644
--- a/oox/source/drawingml/textbodypropertiescontext.cxx
+++ b/oox/source/drawingml/textbodypropertiescontext.cxx
@@ -22,13 +22,22 @@
 #include <com/sun/star/text/WritingMode.hpp>
 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
 #include <drawingml/textbodyproperties.hxx>
+#include <drawingml/textbody.hxx>
+#include <drawingml/customshapegeometry.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
 #include <oox/helper/attributelist.hxx>
 #include <oox/helper/propertymap.hxx>
 #include <oox/token/namespaces.hxx>
 #include <oox/token/properties.hxx>
 #include <oox/token/tokens.hxx>
+#include <svx/EnhancedCustomShapeGeometry.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/sequence.hxx>
 
 using namespace ::oox::core;
 using namespace ::com::sun::star;
@@ -41,9 +50,17 @@ namespace oox { namespace drawingml {
 
 // CT_TextBodyProperties
 TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper const & rParent,
+    const AttributeList& rAttribs, ShapePtr pShapePtr )
+: TextBodyPropertiesContext( rParent, rAttribs, pShapePtr->getTextBody()->getTextProperties() )
+{
+    mpShapePtr = pShapePtr;
+}
+
+TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper const & rParent,
     const AttributeList& rAttribs, TextBodyProperties& rTextBodyProp )
 : ContextHandler2( rParent )
 , mrTextBodyProp( rTextBodyProp )
+, mpShapePtr( nullptr )
 {
     // ST_TextWrappingType
     sal_Int32 nWrappingType = rAttribs.getToken( XML_wrap, XML_square );
@@ -111,12 +128,25 @@ TextBodyPropertiesContext::TextBodyPropertiesContext( ContextHandler2Helper cons
     mrTextBodyProp.maPropertyMap.setProperty( PROP_TextFitToSize, drawing::TextFitToSizeType_NONE);
 }
 
-ContextHandlerRef TextBodyPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& /*rAttribs*/)
+ContextHandlerRef TextBodyPropertiesContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
 {
     switch( aElementToken )
     {
             // Sequence
             case A_TOKEN( prstTxWarp ):     // CT_PresetTextShape
+                if( mpShapePtr )
+                {
+                    const OptValue<OUString> sPrst = rAttribs.getString( XML_prst );
+                    if( sPrst.has() )
+                    {
+                        mrTextBodyProp.msPrst = sPrst.get();
+                        if( mrTextBodyProp.msPrst != "textNoShape" )
+                            return new PresetTextShapeContext( *this, rAttribs,
+                                                           *( mpShapePtr->getCustomShapeProperties() ) );
+                    }
+                }
+                break;
+
             case A_TOKEN( prot ):           // CT_TextProtectionProperty
                 break;
 
diff --git a/oox/source/ppt/pptshapecontext.cxx b/oox/source/ppt/pptshapecontext.cxx
index 304fdb933860..6b4a7fb60631 100644
--- a/oox/source/ppt/pptshapecontext.cxx
+++ b/oox/source/ppt/pptshapecontext.cxx
@@ -173,7 +173,7 @@ ContextHandlerRef PPTShapeContext::onCreateContext( sal_Int32 aElementToken, con
             oox::drawingml::TextBodyPtr xTextBody( new oox::drawingml::TextBody( mpShapePtr->getTextBody() ) );
             xTextBody->getTextProperties().maPropertyMap.setProperty( PROP_FontIndependentLineSpacing, true );
             mpShapePtr->setTextBody( xTextBody );
-            return new oox::drawingml::TextBodyContext( *this, *xTextBody );
+            return new oox::drawingml::TextBodyContext( *this, mpShapePtr );
         }
         case PPT_TOKEN( txXfrm ):
         {
diff --git a/sd/qa/unit/data/pptx/tdf116350-texteffects.pptx b/sd/qa/unit/data/pptx/tdf116350-texteffects.pptx
new file mode 100644
index 000000000000..52a3fe000a9b
Binary files /dev/null and b/sd/qa/unit/data/pptx/tdf116350-texteffects.pptx differ
diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx
index 92258796d507..0607da45b22d 100644
--- a/sd/qa/unit/export-tests-ooxml2.cxx
+++ b/sd/qa/unit/export-tests-ooxml2.cxx
@@ -10,6 +10,7 @@
 #include "sdmodeltestbase.hxx"
 #include <Outliner.hxx>
 #include <comphelper/propertysequence.hxx>
+#include <comphelper/sequence.hxx>
 #include <svl/stritem.hxx>
 #include <editeng/editobj.hxx>
 #include <editeng/outlobj.hxx>
@@ -144,6 +145,7 @@ public:
     void testTdf104786();
     void testTdf104789();
     void testOpenDocumentAsReadOnly();
+    void testTdf116350TextEffects();
 
     CPPUNIT_TEST_SUITE(SdOOXMLExportTest2);
 
@@ -211,6 +213,7 @@ public:
     CPPUNIT_TEST(testTdf104786);
     CPPUNIT_TEST(testTdf104789);
     CPPUNIT_TEST(testOpenDocumentAsReadOnly);
+    CPPUNIT_TEST(testTdf116350TextEffects);
 
     CPPUNIT_TEST_SUITE_END();
 
@@ -1689,6 +1692,53 @@ void SdOOXMLExportTest2::testOpenDocumentAsReadOnly()
     xDocShRef->DoClose();
 }
 
+static inline double getAdjustmentValue( uno::Reference<beans::XPropertySet>& xSet )
+{
+    auto aGeomPropSeq = xSet->getPropertyValue( "CustomShapeGeometry" )
+                            .get<uno::Sequence<beans::PropertyValue>>();
+    auto aGeomPropVec
+        = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>(
+            aGeomPropSeq );
+
+    const OUString sName = "AdjustmentValues";
+    auto aIterator = std::find_if(
+        aGeomPropVec.begin(), aGeomPropVec.end(),
+        [sName]( const beans::PropertyValue& rValue ) { return rValue.Name == sName; } );
+
+    if (aIterator != aGeomPropVec.end())
+    {
+        uno::Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustment;
+        double fResult;
+        aIterator->Value >>= aAdjustment;
+        aAdjustment[0].Value >>= fResult;
+        return fResult;
+    }
+
+    return -1.0;
+}
+
+void SdOOXMLExportTest2::testTdf116350TextEffects()
+{
+    ::sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc( "sd/qa/unit/data/pptx/tdf116350-texteffects.pptx" ), PPTX );
+
+    // Default angle for ArchUp
+    uno::Reference<beans::XPropertySet> xShape0( getShapeFromPage( 0, 0, xDocShRef ) );
+    double fAdjust = getAdjustmentValue( xShape0 );
+    CPPUNIT_ASSERT_EQUAL( 180.0, fAdjust );
+
+    // Default angle for ArchDown
+    uno::Reference<beans::XPropertySet> xShape14( getShapeFromPage( 14, 0, xDocShRef ) );
+    fAdjust = getAdjustmentValue( xShape14 );
+    CPPUNIT_ASSERT_EQUAL( 0.0, fAdjust );
+
+    // Angle directly set
+    uno::Reference<beans::XPropertySet> xShape1( getShapeFromPage( 1, 0, xDocShRef ) );
+    fAdjust = getAdjustmentValue( xShape1 );
+    CPPUNIT_ASSERT_EQUAL( 213.25, fAdjust );
+
+    xDocShRef->DoClose();
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest2);
 
 CPPUNIT_PLUGIN_IMPLEMENT();


More information about the Libreoffice-commits mailing list