diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2018-07-20 17:21:43 +0200 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2018-08-20 10:12:58 +0200 |
commit | b56857dbd21083f5d41eaf4c0f08db1977cf8d2e (patch) | |
tree | ed6ed8824418409092f65625c2b312744955906b | |
parent | 72fece73fbda7dc9fa34c4189cd9dfa10c9f2c51 (diff) |
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@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/58838
Reviewed-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r-- | oox/Library_oox.mk | 1 | ||||
-rw-r--r-- | oox/inc/drawingml/presetgeometrynames.hxx | 23 | ||||
-rw-r--r-- | oox/inc/drawingml/textbodycontext.hxx | 2 | ||||
-rw-r--r-- | oox/inc/drawingml/textbodyproperties.hxx | 1 | ||||
-rw-r--r-- | oox/inc/drawingml/textbodypropertiescontext.hxx | 5 | ||||
-rw-r--r-- | oox/source/drawingml/presetgeometrynames.cxx | 108 | ||||
-rw-r--r-- | oox/source/drawingml/shape.cxx | 185 | ||||
-rw-r--r-- | oox/source/drawingml/shapecontext.cxx | 4 | ||||
-rw-r--r-- | oox/source/drawingml/textbodycontext.cxx | 12 | ||||
-rw-r--r-- | oox/source/drawingml/textbodyproperties.cxx | 1 | ||||
-rw-r--r-- | oox/source/drawingml/textbodypropertiescontext.cxx | 32 | ||||
-rw-r--r-- | oox/source/ppt/pptshapecontext.cxx | 2 | ||||
-rw-r--r-- | sd/qa/unit/data/pptx/tdf116350-texteffects.pptx | bin | 0 -> 38359 bytes | |||
-rw-r--r-- | sd/qa/unit/export-tests-ooxml2.cxx | 50 |
14 files changed, 421 insertions, 5 deletions
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 Binary files differnew file mode 100644 index 000000000000..52a3fe000a9b --- /dev/null +++ b/sd/qa/unit/data/pptx/tdf116350-texteffects.pptx 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(); |