1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <oox/drawingml/shape.hxx>
21 #include <drawingml/customshapeproperties.hxx>
22 #include <oox/drawingml/theme.hxx>
23 #include <drawingml/fillproperties.hxx>
24 #include <drawingml/graphicproperties.hxx>
25 #include <drawingml/scene3dcontext.hxx>
26 #include <drawingml/lineproperties.hxx>
27 #include <drawingml/presetgeometrynames.hxx>
28 #include "effectproperties.hxx"
29 #include <oox/drawingml/shapepropertymap.hxx>
30 #include <drawingml/textbody.hxx>
31 #include <drawingml/textparagraph.hxx>
32 #include <drawingml/ThemeOverrideFragmentHandler.hxx>
33 #include <drawingml/table/tableproperties.hxx>
34 #include <oox/drawingml/chart/chartconverter.hxx>
35 #include <drawingml/chart/chartspacefragment.hxx>
36 #include <drawingml/chart/chartspacemodel.hxx>
37 #include <o3tl/safeint.hxx>
38 #include <oox/ppt/pptimport.hxx>
39 #include <oox/vml/vmldrawing.hxx>
40 #include <oox/vml/vmlshape.hxx>
41 #include <oox/vml/vmlshapecontainer.hxx>
42 #include <oox/core/xmlfilterbase.hxx>
43 #include <oox/helper/graphichelper.hxx>
44 #include <oox/helper/propertyset.hxx>
45 #include <oox/helper/modelobjecthelper.hxx>
46 #include <oox/mathml/importutils.hxx>
47 #include <oox/mathml/import.hxx>
48 #include <oox/token/properties.hxx>
49 #include "diagram/diagram.hxx"
50 
51 #include <comphelper/classids.hxx>
52 #include <comphelper/propertysequence.hxx>
53 #include <comphelper/propertyvalue.hxx>
54 #include <comphelper/sequence.hxx>
55 #include <tools/diagnose_ex.h>
56 #include <tools/gen.hxx>
57 #include <tools/globname.hxx>
58 #include <tools/mapunit.hxx>
59 #include <editeng/unoprnms.hxx>
60 #include <com/sun/star/awt/Size.hpp>
61 #include <com/sun/star/awt/XBitmap.hpp>
62 #include <com/sun/star/awt/FontWeight.hpp>
63 #include <com/sun/star/graphic/XGraphic.hpp>
64 #include <com/sun/star/container/XNamed.hpp>
65 #include <com/sun/star/container/XNameContainer.hpp>
66 #include <com/sun/star/beans/XMultiPropertySet.hpp>
67 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
68 #include <com/sun/star/xml/AttributeData.hpp>
69 #include <com/sun/star/xml/dom/XDocument.hpp>
70 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
71 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
72 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
73 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
74 #include <com/sun/star/drawing/XShapes.hpp>
75 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
76 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
77 #include <com/sun/star/embed/XEmbeddedObject.hpp>
78 #include <com/sun/star/text/XText.hpp>
79 #include <com/sun/star/table/BorderLine2.hpp>
80 #include <com/sun/star/table/ShadowFormat.hpp>
81 #include <com/sun/star/chart2/XChartDocument.hpp>
82 #include <com/sun/star/style/ParagraphAdjust.hpp>
83 #include <com/sun/star/io/XOutputStream.hpp>
84 
85 #include <basegfx/point/b2dpoint.hxx>
86 #include <basegfx/polygon/b2dpolygon.hxx>
87 #include <basegfx/matrix/b2dhommatrix.hxx>
88 #include <com/sun/star/document/XActionLockable.hpp>
89 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
90 #include <svl/outstrm.hxx>
91 #include <svx/svdtrans.hxx>
92 #include <unotools/streamwrap.hxx>
93 #include <unotools/fltrcfg.hxx>
94 #include <vcl/graph.hxx>
95 #include <vcl/graphicfilter.hxx>
96 #include <vcl/svapp.hxx>
97 #include <vcl/wmfexternal.hxx>
98 #include <sal/log.hxx>
99 #include <svx/unoapi.hxx>
100 #include <svx/unoshape.hxx>
101 #include <svx/xfillit0.hxx>
102 #include <svx/sdtaitm.hxx>
103 #include <svx/DiagramDataInterface.hxx>
104 
105 #include <vcl/wmf.hxx>
106 
107 using namespace ::oox::core;
108 using namespace ::com::sun::star;
109 using namespace ::com::sun::star::uno;
110 using namespace ::com::sun::star::beans;
111 using namespace ::com::sun::star::frame;
112 using namespace ::com::sun::star::text;
113 using namespace ::com::sun::star::drawing;
114 using namespace ::com::sun::star::style;
115 
116 namespace oox { namespace drawingml {
117 
Shape(const sal_Char * pServiceName,bool bDefaultHeight)118 Shape::Shape( const sal_Char* pServiceName, bool bDefaultHeight )
119 : mpLinePropertiesPtr( new LineProperties )
120 , mpShapeRefLinePropPtr( new LineProperties )
121 , mpFillPropertiesPtr( new FillProperties )
122 , mpShapeRefFillPropPtr( new FillProperties )
123 , mpGraphicPropertiesPtr( new GraphicProperties )
124 , mpCustomShapePropertiesPtr( new CustomShapeProperties )
125 , mp3DPropertiesPtr( new Shape3DProperties )
126 , mpEffectPropertiesPtr( new EffectProperties )
127 , mpShapeRefEffectPropPtr( new EffectProperties )
128 , mpMasterTextListStyle( new TextListStyle )
129 , mnSubType( 0 )
130 , meFrameType( FRAMETYPE_GENERIC )
131 , mnRotation( 0 )
132 , mnDiagramRotation( 0 )
133 , mbFlipH( false )
134 , mbFlipV( false )
135 , mbHidden( false )
136 , mbHiddenMasterShape( false )
137 , mbLocked( false )
138 , mbLockedCanvas( false )
139 , mbWps( false )
140 , mbTextBox( false )
141 , mbHasLinkedTxbx( false )
142 , maDiagramDoms( 0 )
143 {
144     if ( pServiceName )
145         msServiceName = OUString::createFromAscii( pServiceName );
146     setDefaults(bDefaultHeight);
147 }
148 
Shape(const ShapePtr & pSourceShape)149 Shape::Shape( const ShapePtr& pSourceShape )
150 : maChildren()
151 , mpTextBody(pSourceShape->mpTextBody)
152 , mpLinePropertiesPtr( pSourceShape->mpLinePropertiesPtr )
153 , mpShapeRefLinePropPtr( pSourceShape->mpShapeRefLinePropPtr )
154 , mpFillPropertiesPtr( pSourceShape->mpFillPropertiesPtr )
155 , mpShapeRefFillPropPtr( pSourceShape->mpShapeRefFillPropPtr )
156 , mpGraphicPropertiesPtr( pSourceShape->mpGraphicPropertiesPtr )
157 , mpCustomShapePropertiesPtr( pSourceShape->mpCustomShapePropertiesPtr )
158 , mpTablePropertiesPtr( pSourceShape->mpTablePropertiesPtr )
159 , mp3DPropertiesPtr( pSourceShape->mp3DPropertiesPtr )
160 , mpEffectPropertiesPtr (pSourceShape->mpEffectPropertiesPtr)
161 , mpShapeRefEffectPropPtr(pSourceShape->mpShapeRefEffectPropPtr)
162 , maShapeProperties( pSourceShape->maShapeProperties )
163 , mpMasterTextListStyle( pSourceShape->mpMasterTextListStyle )
164 , mxShape()
165 , msServiceName( pSourceShape->msServiceName )
166 , msName( pSourceShape->msName )
167 , msInternalName( pSourceShape->msInternalName )
168 , msId( pSourceShape->msId )
169 , mnSubType( pSourceShape->mnSubType )
170 , moSubTypeIndex( pSourceShape->moSubTypeIndex )
171 , maShapeStyleRefs( pSourceShape->maShapeStyleRefs )
172 , maSize( pSourceShape->maSize )
173 , maPosition( pSourceShape->maPosition )
174 , meFrameType( pSourceShape->meFrameType )
175 , mnRotation( pSourceShape->mnRotation )
176 , mnDiagramRotation( pSourceShape->mnDiagramRotation )
177 , mbFlipH( pSourceShape->mbFlipH )
178 , mbFlipV( pSourceShape->mbFlipV )
179 , mbHidden( pSourceShape->mbHidden )
180 , mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape )
181 , mbLocked( pSourceShape->mbLocked )
182 , mbLockedCanvas( pSourceShape->mbLockedCanvas )
183 , mbWps( pSourceShape->mbWps )
184 , mbTextBox( pSourceShape->mbTextBox )
185 , maLinkedTxbxAttr()
186 , mbHasLinkedTxbx(false)
187 , maDiagramDoms( pSourceShape->maDiagramDoms )
188 , mnZOrder(pSourceShape->mnZOrder)
189 , mnZOrderOff(pSourceShape->mnZOrderOff)
190 , mnDataNodeType(pSourceShape->mnDataNodeType)
191 , mfAspectRatio(pSourceShape->mfAspectRatio)
192 , mbUseBgFill(pSourceShape->mbUseBgFill)
193 {}
194 
~Shape()195 Shape::~Shape()
196 {
197 }
198 
getTableProperties()199 table::TablePropertiesPtr const & Shape::getTableProperties()
200 {
201     if ( !mpTablePropertiesPtr.get() )
202         mpTablePropertiesPtr.reset( new table::TableProperties() );
203     return mpTablePropertiesPtr;
204 }
205 
setDefaults(bool bHeight)206 void Shape::setDefaults(bool bHeight)
207 {
208     maDefaultShapeProperties.setProperty(PROP_TextAutoGrowHeight, false);
209     maDefaultShapeProperties.setProperty(PROP_TextWordWrap, true);
210     maDefaultShapeProperties.setProperty(PROP_TextLeftDistance, static_cast< sal_Int32 >( 250 ));
211     maDefaultShapeProperties.setProperty(PROP_TextUpperDistance, static_cast< sal_Int32 >( 125 ));
212     maDefaultShapeProperties.setProperty(PROP_TextRightDistance, static_cast< sal_Int32 >( 250 ));
213     maDefaultShapeProperties.setProperty(PROP_TextLowerDistance, static_cast< sal_Int32 >( 125 ));
214     if (bHeight)
215         maDefaultShapeProperties.setProperty(PROP_CharHeight, static_cast< float >( 18.0 ));
216     maDefaultShapeProperties.setProperty(PROP_TextVerticalAdjust, TextVerticalAdjust_TOP);
217     maDefaultShapeProperties.setProperty(PROP_ParaAdjust,
218                                          static_cast<sal_Int16>(ParagraphAdjust_LEFT));
219 }
220 
setOleObjectType()221 ::oox::vml::OleObjectInfo& Shape::setOleObjectType()
222 {
223     OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setOleObjectType - multiple frame types" );
224     meFrameType = FRAMETYPE_OLEOBJECT;
225     mxOleObjectInfo.reset( new ::oox::vml::OleObjectInfo( true ) );
226     return *mxOleObjectInfo;
227 }
228 
setChartType(bool bEmbedShapes)229 ChartShapeInfo& Shape::setChartType( bool bEmbedShapes )
230 {
231     OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setChartType - multiple frame types" );
232     meFrameType = FRAMETYPE_CHART;
233     if (mbWps)
234         msServiceName = "com.sun.star.drawing.temporaryForXMLImportOLE2Shape";
235     else
236         msServiceName = "com.sun.star.drawing.OLE2Shape";
237     mxChartShapeInfo.reset( new ChartShapeInfo( bEmbedShapes ) );
238     return *mxChartShapeInfo;
239 }
240 
setDiagramType()241 void Shape::setDiagramType()
242 {
243     OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setDiagramType - multiple frame types" );
244     meFrameType = FRAMETYPE_DIAGRAM;
245     msServiceName = "com.sun.star.drawing.GroupShape";
246     mnSubType = 0;
247 }
248 
setTableType()249 void Shape::setTableType()
250 {
251     OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setTableType - multiple frame types" );
252     meFrameType = FRAMETYPE_TABLE;
253     msServiceName = "com.sun.star.drawing.TableShape";
254     mnSubType = 0;
255 }
256 
setServiceName(const sal_Char * pServiceName)257 void Shape::setServiceName( const sal_Char* pServiceName )
258 {
259     if ( pServiceName )
260         msServiceName = OUString::createFromAscii( pServiceName );
261 }
262 
getShapeStyleRef(sal_Int32 nRefType) const263 const ShapeStyleRef* Shape::getShapeStyleRef( sal_Int32 nRefType ) const
264 {
265     ShapeStyleRefMap::const_iterator aIt = maShapeStyleRefs.find( nRefType );
266     return (aIt == maShapeStyleRefs.end()) ? nullptr : &aIt->second;
267 }
268 
addShape(::oox::core::XmlFilterBase & rFilterBase,const Theme * pTheme,const Reference<XShapes> & rxShapes,const basegfx::B2DHomMatrix & aTransformation,FillProperties & rShapeOrParentShapeFillProps,ShapeIdMap * pShapeMap,bool bInGroup)269 void Shape::addShape(
270         ::oox::core::XmlFilterBase& rFilterBase,
271         const Theme* pTheme,
272         const Reference< XShapes >& rxShapes,
273         const basegfx::B2DHomMatrix& aTransformation,
274         FillProperties& rShapeOrParentShapeFillProps,
275         ShapeIdMap* pShapeMap,
276         bool bInGroup )
277 {
278     SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId << "'");
279 
280     try
281     {
282         OUString sServiceName( msServiceName );
283         if( !sServiceName.isEmpty() )
284         {
285             basegfx::B2DHomMatrix aMatrix( aTransformation );
286             Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, false, false, aMatrix, rShapeOrParentShapeFillProps, bInGroup ) );
287 
288             if( pShapeMap && !msId.isEmpty() )
289             {
290                 (*pShapeMap)[ msId ] = shared_from_this();
291             }
292 
293             // if this is a group shape, we have to add also each child shape
294             Reference< XShapes > xShapes( xShape, UNO_QUERY );
295             if ( xShapes.is() )
296                 addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aMatrix );
297 
298             if( meFrameType == FRAMETYPE_DIAGRAM )
299             {
300                 keepDiagramCompatibilityInfo();
301                 if( !SvtFilterOptions::Get().IsSmartArt2Shape() )
302                     convertSmartArtToMetafile( rFilterBase );
303             }
304         }
305     }
306     catch( const Exception& )
307     {
308         TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" );
309     }
310 }
311 
setLockedCanvas(bool bLockedCanvas)312 void Shape::setLockedCanvas(bool bLockedCanvas)
313 {
314     mbLockedCanvas = bLockedCanvas;
315 }
316 
setWps(bool bWps)317 void Shape::setWps(bool bWps)
318 {
319     mbWps = bWps;
320 }
321 
setTextBox(bool bTextBox)322 void Shape::setTextBox(bool bTextBox)
323 {
324     mbTextBox = bTextBox;
325 }
326 
applyShapeReference(const Shape & rReferencedShape,bool bUseText)327 void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText )
328 {
329     SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape.msId << "' to '" << msId << "'");
330 
331     if ( rReferencedShape.mpTextBody.get() && bUseText )
332         mpTextBody = std::make_shared<TextBody>( *rReferencedShape.mpTextBody );
333     else
334         mpTextBody.reset();
335     maShapeProperties = rReferencedShape.maShapeProperties;
336     mpShapeRefLinePropPtr = std::make_shared<LineProperties>( rReferencedShape.getActualLineProperties(nullptr) );
337     mpShapeRefFillPropPtr = std::make_shared<FillProperties>( rReferencedShape.getActualFillProperties(nullptr, nullptr) );
338     mpCustomShapePropertiesPtr = std::make_shared<CustomShapeProperties>( *rReferencedShape.mpCustomShapePropertiesPtr );
339     mpTablePropertiesPtr = table::TablePropertiesPtr( rReferencedShape.mpTablePropertiesPtr.get() ? new table::TableProperties( *rReferencedShape.mpTablePropertiesPtr ) : nullptr );
340     mpShapeRefEffectPropPtr = std::make_shared<EffectProperties>( rReferencedShape.getActualEffectProperties(nullptr) );
341     mpMasterTextListStyle = std::make_shared<TextListStyle>( *rReferencedShape.mpMasterTextListStyle );
342     maSize = rReferencedShape.maSize;
343     maPosition = rReferencedShape.maPosition;
344     mnRotation = rReferencedShape.mnRotation;
345     mbFlipH = rReferencedShape.mbFlipH;
346     mbFlipV = rReferencedShape.mbFlipV;
347     mbHidden = rReferencedShape.mbHidden;
348     mbLocked = rReferencedShape.mbLocked;
349 }
350 
351 struct ActionLockGuard
352 {
ActionLockGuardoox::drawingml::ActionLockGuard353     explicit ActionLockGuard(Reference<drawing::XShape> const& xShape)
354         : m_xLockable(xShape, UNO_QUERY)
355     {
356         if (m_xLockable.is()) {
357             m_xLockable->addActionLock();
358         }
359     }
~ActionLockGuardoox::drawingml::ActionLockGuard360     ~ActionLockGuard()
361     {
362         if (m_xLockable.is()) {
363             m_xLockable->removeActionLock();
364         }
365     }
366 private:
367     Reference<document::XActionLockable> m_xLockable;
368 };
369 
370 // for group shapes, the following method is also adding each child
addChildren(XmlFilterBase & rFilterBase,Shape & rMaster,const Theme * pTheme,const Reference<XShapes> & rxShapes,ShapeIdMap * pShapeMap,const basegfx::B2DHomMatrix & aTransformation)371 void Shape::addChildren(
372         XmlFilterBase& rFilterBase,
373         Shape& rMaster,
374         const Theme* pTheme,
375         const Reference< XShapes >& rxShapes,
376         ShapeIdMap* pShapeMap,
377         const basegfx::B2DHomMatrix& aTransformation )
378 {
379     basegfx::B2DHomMatrix aChildTransformation;
380 
381     aChildTransformation.translate(-maChPosition.X, -maChPosition.Y);
382     aChildTransformation.scale(1/(maChSize.Width ? maChSize.Width : 1.0), 1/(maChSize.Height ? maChSize.Height : 1.0));
383 
384     // Child position and size is typically non-zero, but it's allowed to have
385     // it like that, and in that case Word ignores the parent transformation
386     // (excluding translate component).
387     if (!mbWps || maChPosition.X || maChPosition.Y || maChSize.Width || maChSize.Height)
388     {
389         aChildTransformation *= aTransformation;
390     }
391     else
392     {
393         basegfx::B2DVector aScale, aTranslate;
394         double fRotate, fShearX;
395         aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
396         aChildTransformation.translate(aTranslate.getX(), aTranslate.getY());
397     }
398 
399     SAL_INFO("oox.drawingml", "Shape::addChildren: parent matrix:\n"
400              << aChildTransformation.get(0, 0) << " "
401              << aChildTransformation.get(0, 1) << " "
402              << aChildTransformation.get(0, 2) << "\n"
403              << aChildTransformation.get(1, 0) << " "
404              << aChildTransformation.get(1, 1) << " "
405              << aChildTransformation.get(1, 2) << "\n"
406              << aChildTransformation.get(2, 0) << " "
407              << aChildTransformation.get(2, 1) << " "
408              << aChildTransformation.get(2, 2));
409 
410     for (auto const& child : rMaster.maChildren)
411     {
412         child->setMasterTextListStyle( mpMasterTextListStyle );
413         child->addShape( rFilterBase, pTheme, rxShapes, aChildTransformation, getFillProperties(), pShapeMap, true );
414     }
415 }
416 
lcl_resetPropertyValue(std::vector<beans::PropertyValue> & rPropVec,const OUString & rName)417 static void lcl_resetPropertyValue( std::vector<beans::PropertyValue>& rPropVec, const OUString& rName )
418 {
419     auto aIterator = std::find_if( rPropVec.begin(), rPropVec.end(),
420         [rName]( const beans::PropertyValue& rValue ) { return rValue.Name == rName; } );
421 
422     if (aIterator != rPropVec.end())
423         rPropVec.erase( aIterator );
424 }
425 
lcl_setPropertyValue(std::vector<beans::PropertyValue> & rPropVec,const OUString & rName,const beans::PropertyValue & rPropertyValue)426 static void lcl_setPropertyValue( std::vector<beans::PropertyValue>& rPropVec,
427                            const OUString& rName,
428                            const beans::PropertyValue& rPropertyValue )
429 {
430     lcl_resetPropertyValue( rPropVec, rName );
431 
432     rPropVec.push_back( rPropertyValue );
433 }
434 
lcl_convertAdjust(ParagraphAdjust eAdjust)435 static SdrTextHorzAdjust lcl_convertAdjust( ParagraphAdjust eAdjust )
436 {
437     if (eAdjust == ParagraphAdjust_LEFT)
438         return SDRTEXTHORZADJUST_LEFT;
439     else if (eAdjust == ParagraphAdjust_RIGHT)
440         return SDRTEXTHORZADJUST_RIGHT;
441     else if (eAdjust == ParagraphAdjust_CENTER)
442         return SDRTEXTHORZADJUST_CENTER;
443     return SDRTEXTHORZADJUST_LEFT;
444 }
445 
lcl_createPresetShape(const uno::Reference<drawing::XShape> & xShape,const OUString & rClass,const OUString & rPresetType,const CustomShapePropertiesPtr & pCustomShapePropertiesPtr,const TextBodyPtr & pTextBody,const GraphicHelper & rGraphicHelper)446 static void lcl_createPresetShape(const uno::Reference<drawing::XShape>& xShape,
447                                          const OUString& rClass, const OUString& rPresetType,
448                                          const CustomShapePropertiesPtr& pCustomShapePropertiesPtr,
449                                          const TextBodyPtr& pTextBody,
450                                          const GraphicHelper& rGraphicHelper)
451 {
452     if (!xShape.is() || !pCustomShapePropertiesPtr || !pTextBody)
453         return;
454 
455     uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter( xShape,
456                                                                        uno::UNO_QUERY );
457 
458     if (!xDefaulter.is() || rClass.isEmpty())
459         return;
460 
461     Reference<XPropertySet> xSet( xShape, UNO_QUERY );
462     if (!xSet.is())
463         return;
464 
465     // The DrawingML shapes from the presetTextWarpDefinitions are mapped to the definitions
466     // in svx/../EnhancedCustomShapeGeometry.cxx, which are used for WordArt shapes from
467     // binary MS Office. Therefore all adjustment values need to be adapted.
468     auto aAdjGdList = pCustomShapePropertiesPtr->getAdjustmentGuideList();
469     Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustment(
470         !aAdjGdList.empty() ? aAdjGdList.size() : 1 );
471 
472     int nIndex = 0;
473     for (const auto& aEntry : aAdjGdList)
474     {
475         double fValue = aEntry.maFormula.toDouble();
476         // then: polar-handle, else: XY-handle
477         // There exist only 8 polar-handles at all in presetTextWarp.
478         if ((rClass == "fontwork-arch-down-curve")
479             || (rClass == "fontwork-arch-down-pour" && aEntry.maName == "adj1")
480             || (rClass == "fontwork-arch-up-curve")
481             || (rClass == "fontwork-arch-up-pour" && aEntry.maName == "adj1")
482             || (rClass == "fontwork-open-circle-curve")
483             || (rClass == "fontwork-open-circle-pour" && aEntry.maName == "adj1")
484             || (rClass == "fontwork-circle-curve")
485             || (rClass == "fontwork-circle-pour" && aEntry.maName == "adj1"))
486         {
487             // DrawingML has 1/60000 degree unit, but WordArt simple degree. Range [0..360[
488             // or range ]-180..180] doesn't matter, because only cos(angle) and
489             // sin(angle) are used.
490             fValue = NormAngle360(fValue / 60000.0);
491         }
492         else
493         {
494             // DrawingML writes adjustment guides as relative value with 100% = 100000,
495             // but WordArt definitions use values absolute in viewBox 0 0 21600 21600,
496             // so scale with 21600/100000 = 0.216, with two exceptions:
497             // X-handles of waves describe increase/decrease relative to horizontal center.
498             // The gdRefR of pour-shapes is not relative to viewBox but to radius.
499             if ((rClass == "mso-spt158" && aEntry.maName == "adj2") // textDoubleWave1
500                 || (rClass == "fontwork-wave" && aEntry.maName == "adj2") // textWave1
501                 || (rClass == "mso-spt157" && aEntry.maName == "adj2") // textWave2
502                 || (rClass == "mso-spt159" && aEntry.maName == "adj2")) // textWave4
503             {
504                 fValue = (fValue + 50000.0) * 0.216;
505             }
506             else if ( (rClass == "fontwork-arch-down-pour" && aEntry.maName == "adj2")
507                     || (rClass == "fontwork-arch-up-pour" && aEntry.maName == "adj2")
508                     || (rClass == "fontwork-open-circle-pour" && aEntry.maName == "adj2")
509                     || (rClass == "fontwork-circle-pour" && aEntry.maName == "adj2"))
510                 {
511                     fValue *= 0.108;
512                 }
513             else
514             {
515                 fValue *= 0.216;
516             }
517         }
518 
519         aAdjustment[nIndex].Value <<= fValue;
520         aAdjustment[nIndex++].State = css::beans::PropertyState_DIRECT_VALUE;
521     }
522 
523     // Set properties
524     xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny( false ) );
525     xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny( false ) );
526     xSet->setPropertyValue( UNO_NAME_FILLSTYLE, uno::makeAny( drawing::FillStyle_SOLID ) );
527 
528     // ToDo: Old binary WordArt does not allow different styles for different paragraphs, so it
529     // was not necessary to examine all paragraphs. Solution for DrawingML is needed.
530     // Currently different alignment of paragraphs are lost, for example.
531     const TextParagraphVector& rParagraphs = pTextBody->getParagraphs();
532     if (!rParagraphs.empty() && !rParagraphs[0]->getRuns().empty())
533     {
534         std::shared_ptr<TextParagraph> pParagraph = rParagraphs[0];
535         std::shared_ptr<TextRun> pRun = pParagraph->getRuns()[0];
536         TextCharacterProperties& pProperties = pRun->getTextCharacterProperties();
537 
538         if (pProperties.moBold.has() && pProperties.moBold.get())
539         {
540             xSet->setPropertyValue( UNO_NAME_CHAR_WEIGHT, uno::makeAny( css::awt::FontWeight::BOLD ) );
541         }
542         if (pProperties.moItalic.has() && pProperties.moItalic.get())
543         {
544             xSet->setPropertyValue( UNO_NAME_CHAR_POSTURE, uno::makeAny( css::awt::FontSlant::FontSlant_ITALIC ) );
545         }
546         if (pProperties.moHeight.has())
547         {
548             sal_Int32 nHeight = pProperties.moHeight.get() / 100;
549             xSet->setPropertyValue( UNO_NAME_CHAR_HEIGHT, uno::makeAny( nHeight ) );
550         }
551         if (pProperties.maFillProperties.maFillColor.isUsed())
552         {
553             const sal_Int32 aFillColor = static_cast<sal_Int32>(
554                 pProperties.maFillProperties.maFillColor.getColor( rGraphicHelper ).GetRGBColor() );
555             xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( aFillColor ) );
556         }
557         else
558         {
559             // Set default color
560             xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( COL_BLACK ) );
561         }
562         {
563             ParagraphAdjust eAdjust = ParagraphAdjust_LEFT;
564             if (pParagraph->getProperties().getParaAdjust())
565                 eAdjust = pParagraph->getProperties().getParaAdjust().get();
566             xSet->setPropertyValue( "ParaAdjust", uno::makeAny( eAdjust ) );
567             SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape );
568             assert(pShape);
569             SdrTextHorzAdjust eHorzAdjust = lcl_convertAdjust( eAdjust );
570             pShape->GetSdrObject()->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust ) );
571         }
572     }
573 
574     // Apply vertical adjustment for text on arc
575     // ToDo: The property is currently not evaluated.
576     SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>(xShape);
577     assert(pShape);
578     if (rClass == "fontwork-arch-up-curve")
579         pShape->GetSdrObject()->SetMergedItem( SdrTextVertAdjustItem( SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM ) );
580     else if (rClass == "fontwork-arch-down-curve")
581         pShape->GetSdrObject()->SetMergedItem( SdrTextVertAdjustItem( SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP ) );
582 
583     // Apply preset shape
584     xDefaulter->createCustomShapeDefaults( rClass );
585 
586     auto aGeomPropSeq = xSet->getPropertyValue( "CustomShapeGeometry" )
587                             .get<uno::Sequence<beans::PropertyValue>>();
588     auto aGeomPropVec
589         = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>(
590             aGeomPropSeq );
591 
592     // Reset old properties
593     const OUString sCoordinateSize( "CoordinateSize" );
594     const OUString sEquations( "Equations" );
595     const OUString sPath( "Path" );
596     const OUString sTextPath( "TextPath" );
597     const OUString sAdjustmentValues( "AdjustmentValues" );
598     const OUString sPresetTextWarp( "PresetTextWarp" );
599 
600     lcl_resetPropertyValue( aGeomPropVec, sCoordinateSize );
601     lcl_resetPropertyValue( aGeomPropVec, sEquations );
602     lcl_resetPropertyValue( aGeomPropVec, sPath );
603     lcl_resetPropertyValue( aGeomPropVec, sAdjustmentValues);
604 
605     bool bFromWordArt(false);
606     pTextBody->getTextProperties().maPropertyMap.getProperty(PROP_FromWordArt) >>= bFromWordArt;
607 
608     bool bScaleX(false);
609     if (!bFromWordArt
610         && (rPresetType == "textArchDown" || rPresetType == "textArchUp"
611             || rPresetType == "textCircle" || rPresetType == "textButton"))
612     {
613         bScaleX = true;
614     }
615 
616     // Apply geometry properties
617     uno::Sequence<beans::PropertyValue> aPropertyValues(
618         comphelper::InitPropertySequence(
619             { { sTextPath, uno::makeAny( true ) },
620                 { "TextPathMode",
621                 uno::Any( drawing::EnhancedCustomShapeTextPathMode_PATH ) },
622                 { "ScaleX", uno::Any(bScaleX) } } ) );
623 
624     lcl_setPropertyValue( aGeomPropVec, sTextPath,
625         comphelper::makePropertyValue( sTextPath, aPropertyValues ) );
626 
627     lcl_setPropertyValue( aGeomPropVec, sPresetTextWarp,
628         comphelper::makePropertyValue( sPresetTextWarp, rPresetType ) );
629 
630     if (!aAdjGdList.empty())
631     {
632         lcl_setPropertyValue( aGeomPropVec, sAdjustmentValues,
633             comphelper::makePropertyValue( sAdjustmentValues, aAdjustment ) );
634     }
635 
636     xSet->setPropertyValue(
637         "CustomShapeGeometry",
638         uno::makeAny(comphelper::containerToSequence(aGeomPropVec)));
639 }
640 
createAndInsert(::oox::core::XmlFilterBase & rFilterBase,const OUString & rServiceName,const Theme * pTheme,const css::uno::Reference<css::drawing::XShapes> & rxShapes,bool bClearText,bool bDoNotInsertEmptyTextBody,basegfx::B2DHomMatrix & aParentTransformation,FillProperties & rShapeOrParentShapeFillProps,bool bInGroup)641 Reference< XShape > const & Shape::createAndInsert(
642         ::oox::core::XmlFilterBase& rFilterBase,
643         const OUString& rServiceName,
644         const Theme* pTheme,
645         const css::uno::Reference< css::drawing::XShapes >& rxShapes,
646         bool bClearText,
647         bool bDoNotInsertEmptyTextBody,
648         basegfx::B2DHomMatrix& aParentTransformation,
649         FillProperties& rShapeOrParentShapeFillProps,
650         bool bInGroup )
651 {
652     bool bIsEmbMedia = false;
653     SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId << "' service='" << rServiceName << "'");
654 
655     formulaimport::XmlStreamBuilder * pMathXml(nullptr);
656     if (mpTextBody.get())
657     {
658         for (auto const& it : mpTextBody->getParagraphs())
659         {
660             if (it->HasMathXml())
661             {
662                 if (!mpTextBody->isEmpty() || pMathXml != nullptr)
663                 {
664                     SAL_WARN("oox.drawingml", "losing a Math object...");
665                 }
666                 else
667                 {
668                     pMathXml = &it->GetMathXml();
669                 }
670             }
671         }
672     }
673 
674     // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height
675     if ( mpTablePropertiesPtr.get() && rServiceName == "com.sun.star.drawing.TableShape" )
676     {
677         maSize.Width = 0;
678         for (auto const& elem : mpTablePropertiesPtr->getTableGrid())
679         {
680             maSize.Width = o3tl::saturating_add(maSize.Width, static_cast<sal_Int32>(elem));
681         }
682         maSize.Height = 0;
683         for (auto const& elem : mpTablePropertiesPtr->getTableRows())
684         {
685             maSize.Height = o3tl::saturating_add(maSize.Height, elem.getHeight());
686         }
687     }
688 
689     awt::Rectangle aShapeRectHmm( maPosition.X / EMU_PER_HMM, maPosition.Y / EMU_PER_HMM, maSize.Width / EMU_PER_HMM, maSize.Height / EMU_PER_HMM );
690 
691     OUString aServiceName;
692     if (pMathXml)
693     {
694         // convert this shape to OLE
695         aServiceName = "com.sun.star.drawing.OLE2Shape";
696         msServiceName = aServiceName;
697         meFrameType = FRAMETYPE_GENERIC; // not OLEOBJECT, no stream in package
698         mnSubType = 0;
699     }
700     else if (rServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
701         mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty())
702     {
703         aServiceName = finalizeServiceName( rFilterBase, "com.sun.star.presentation.MediaShape", aShapeRectHmm );
704         bIsEmbMedia = true;
705     }
706     else
707     {
708         aServiceName = finalizeServiceName( rFilterBase, rServiceName, aShapeRectHmm );
709     }
710     // Use custom shape instead of GraphicObjectShape if the image is cropped to
711     // shape. Except rectangle, which does not require further cropping
712     bool bIsCroppedGraphic = (aServiceName == "com.sun.star.drawing.GraphicObjectShape" && mpCustomShapePropertiesPtr->getShapePresetType() >= 0
713             && mpCustomShapePropertiesPtr->getShapePresetType() != XML_Rect && mpCustomShapePropertiesPtr->getShapePresetType() != XML_rect);
714     bool bIsCustomShape = ( aServiceName == "com.sun.star.drawing.CustomShape" ||
715                             aServiceName == "com.sun.star.drawing.ConnectorShape" ||
716                             bIsCroppedGraphic);
717     if(bIsCroppedGraphic)
718     {
719         aServiceName = "com.sun.star.drawing.CustomShape";
720         mpGraphicPropertiesPtr->mbIsCustomShape = true;
721     }
722     bool bUseRotationTransform = ( !mbWps ||
723             aServiceName == "com.sun.star.drawing.LineShape" ||
724             aServiceName == "com.sun.star.drawing.GroupShape" ||
725             mbFlipH ||
726             mbFlipV );
727 
728     basegfx::B2DHomMatrix aTransformation;
729 
730     if (bUseRotationTransform && mnDiagramRotation != 0)
731     {
732         // rotate diagram's shape around object's center before sizing
733         aTransformation.translate(-0.5, -0.5);
734         aTransformation.rotate(basegfx::deg2rad(mnDiagramRotation / 60000.0));
735         aTransformation.translate(0.5, 0.5);
736     }
737 
738     if( maSize.Width != 1 || maSize.Height != 1)
739     {
740         // take care there are no zeros used by error
741         aTransformation.scale(
742             maSize.Width ? maSize.Width : 1.0,
743             maSize.Height ? maSize.Height : 1.0 );
744     }
745 
746     bool bNoTranslation = !aParentTransformation.isIdentity();
747     if( mbFlipH || mbFlipV || mnRotation != 0 || bNoTranslation )
748     {
749         // calculate object's center
750         basegfx::B2DPoint aCenter(0.5, 0.5);
751         aCenter *= aTransformation;
752 
753         // center object at origin
754         aTransformation.translate( -aCenter.getX(), -aCenter.getY() );
755 
756         if( !bIsCustomShape && ( mbFlipH || mbFlipV ) )
757         {
758             // mirror around object's center
759             aTransformation.scale( mbFlipH ? -1.0 : 1.0, mbFlipV ? -1.0 : 1.0 );
760         }
761 
762         if( bUseRotationTransform )
763         {
764             // OOXML flips shapes before rotating them.
765             if( bIsCustomShape )
766             {
767                 basegfx::B2DVector aScale, aTranslate;
768                 double fRotate, fShearX;
769                 aParentTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
770                 // A negative scale means that the shape needs to be flipped
771                 if(aScale.getX() < 0)
772                 {
773                     mbFlipH = !mbFlipH;
774                     aTransformation.scale(-1, 1);
775                 }
776                 if(aScale.getY() < 0)
777                 {
778                     mbFlipV = !mbFlipV;
779                     aTransformation.scale(1, -1);
780                 }
781             }
782             // rotate around object's center
783             aTransformation.rotate(basegfx::deg2rad(static_cast<double>(mnRotation) / 60000.0));
784         }
785 
786         // move object back from center
787         aTransformation.translate( aCenter.getX(), aCenter.getY() );
788     }
789 
790     if( maPosition.X != 0 || maPosition.Y != 0)
791     {
792         // if global position is used, add it to transformation
793         if (mbWps && !bInGroup)
794             aTransformation.translate( maPosition.X * EMU_PER_HMM, maPosition.Y * EMU_PER_HMM);
795         else
796             aTransformation.translate( maPosition.X, maPosition.Y );
797     }
798 
799     aTransformation = aParentTransformation*aTransformation;
800     aParentTransformation = aTransformation;
801     aTransformation.scale(1/double(EMU_PER_HMM), 1/double(EMU_PER_HMM));
802 
803     if( bIsCustomShape && mbFlipH != mbFlipV )
804     {
805         basegfx::B2DVector aScale, aTranslate;
806         double fRotate, fShearX;
807         aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
808 
809         if(fRotate != 0)
810         {
811             // calculate object's center
812             basegfx::B2DPoint aCenter(0.5, 0.5);
813             aCenter *= aTransformation;
814             aTransformation.translate( -aCenter.getX(), -aCenter.getY() );
815             // OOXML flips shapes before rotating them, so the rotation needs to be inverted
816             aTransformation.rotate( fRotate * -2.0 );
817             aTransformation.translate( aCenter.getX(), aCenter.getY() );
818         }
819     }
820 
821     // special for lineshape
822     if ( aServiceName == "com.sun.star.drawing.LineShape" )
823     {
824         ::basegfx::B2DPolygon aPoly;
825         aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
826         aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) );
827         aPoly.transform( aTransformation );
828 
829         // now creating the corresponding PolyPolygon
830         sal_Int32 i, nNumPoints = aPoly.count();
831         uno::Sequence< awt::Point > aPointSequence( nNumPoints );
832         awt::Point* pPoints = aPointSequence.getArray();
833         uno::Reference<lang::XServiceInfo> xModelInfo(rFilterBase.getModel(), uno::UNO_QUERY);
834         bool bIsWriter = xModelInfo->supportsService("com.sun.star.text.TextDocument");
835         for( i = 0; i < nNumPoints; ++i )
836         {
837             const basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) );
838 
839             // tdf#106792 Not needed anymore due to the change in SdrPathObj::NbcResize:
840             // tdf#96674: Guard against zero width or height.
841 
842             if (bIsWriter && bNoTranslation)
843                 // Writer's draw page is in twips, and these points get passed
844                 // to core without any unit conversion when Writer
845                 // postprocesses only the group shape itself.
846                 pPoints[i] = awt::Point(static_cast<sal_Int32>(convertMm100ToTwip(aPoint.getX())), static_cast<sal_Int32>(convertMm100ToTwip(aPoint.getY())));
847             else
848                 pPoints[i] = awt::Point(static_cast<sal_Int32>(aPoint.getX()), static_cast<sal_Int32>(aPoint.getY()));
849         }
850         uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 );
851         aPolyPolySequence.getArray()[ 0 ] = aPointSequence;
852 
853         maShapeProperties.setProperty(PROP_PolyPolygon, aPolyPolySequence);
854     }
855     else if ( aServiceName == "com.sun.star.drawing.ConnectorShape" )
856     {
857         ::basegfx::B2DPolygon aPoly;
858         aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
859         aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) );
860         aPoly.transform( aTransformation );
861 
862         basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) );
863         basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) );
864         awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) );
865         awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) );
866 
867         maShapeProperties.setProperty(PROP_StartPosition, aAWTStartPosition);
868         maShapeProperties.setProperty(PROP_EndPosition, aAWTEndPosition);
869     }
870     else
871     {
872         // now set transformation for this object
873         HomogenMatrix3 aMatrix;
874 
875         aMatrix.Line1.Column1 = aTransformation.get(0,0);
876         aMatrix.Line1.Column2 = aTransformation.get(0,1);
877         aMatrix.Line1.Column3 = aTransformation.get(0,2);
878 
879         aMatrix.Line2.Column1 = aTransformation.get(1,0);
880         aMatrix.Line2.Column2 = aTransformation.get(1,1);
881         aMatrix.Line2.Column3 = aTransformation.get(1,2);
882 
883         aMatrix.Line3.Column1 = aTransformation.get(2,0);
884         aMatrix.Line3.Column2 = aTransformation.get(2,1);
885         aMatrix.Line3.Column3 = aTransformation.get(2,2);
886 
887         maShapeProperties.setProperty(PROP_Transformation, aMatrix);
888     }
889 
890     Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
891     if ( !mxShape.is() )
892         mxShape.set( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW );
893 
894     Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
895     if (xSet.is())
896     {
897         if( !msName.isEmpty() )
898         {
899             Reference< container::XNamed > xNamed( mxShape, UNO_QUERY );
900             if( xNamed.is() )
901                 xNamed->setName( msName );
902         }
903         if( !msDescription.isEmpty() )
904         {
905             const OUString sDescription( "Description" );
906             xSet->setPropertyValue( sDescription, Any( msDescription ) );
907         }
908         if (aServiceName != "com.sun.star.text.TextFrame")
909             rxShapes->add( mxShape );
910 
911         if ( mbHidden || mbHiddenMasterShape )
912         {
913             SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId << "'");
914             const OUString sVisible( "Visible" );
915             xSet->setPropertyValue( sVisible, Any( false ) );
916             // In Excel hidden means not printed, let's use visibility for now until that's handled separately
917             const OUString sPrintable( "Printable" );
918             xSet->setPropertyValue( sPrintable, Any( false ) );
919         }
920 
921         if (mbLocked)
922         {
923             xSet->setPropertyValue("MoveProtect", Any(true));
924             xSet->setPropertyValue("SizeProtect", Any(true));
925         }
926 
927         ActionLockGuard const alg(mxShape);
928 
929         // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape
930         if ( bClearText )
931         {
932             uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
933             if ( xText.is() )
934             {
935                 xText->setString( "" );
936             }
937         }
938 
939         if (pMathXml)
940         {
941             // the "EmbeddedObject" property is read-only, so we have to create
942             // the shape first, and it can be read only after the shape is
943             // inserted into the document, so delay the actual import until here
944             SvGlobalName name(SO3_SM_CLASSID);
945             xSet->setPropertyValue("CLSID", uno::makeAny(name.GetHexName()));
946             uno::Reference<embed::XEmbeddedObject> const xObj(
947                 xSet->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY);
948             if (xObj.is())
949             {
950                 uno::Reference<uno::XInterface> const xMathModel(xObj->getComponent());
951                 oox::FormulaImportBase *const pMagic(
952                         dynamic_cast<oox::FormulaImportBase*>(xMathModel.get()));
953                 assert(pMagic);
954                 pMagic->readFormulaOoxml(*pMathXml);
955             }
956         }
957 
958         const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper();
959 
960         ::Color nLinePhClr(0xffffffff);
961         ::Color nFillPhClr(0xffffffff);
962         // TODO: use ph color when applying effect properties
963         //sal_Int32 nEffectPhClr = -1;
964 
965         if( pTheme )
966         {
967             if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) )
968             {
969                 LineProperties aLineProperties;
970                 aLineProperties.maLineFill.moFillType = XML_noFill;
971                 if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) )
972                     aLineProperties.assignUsed( *pLineProps );
973                 nLinePhClr = pLineRef->maPhClr.getColor( rGraphicHelper );
974 
975                 // Store style-related properties to InteropGrabBag to be able to export them back
976                 uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
977                 {
978                     {"SchemeClr", uno::makeAny(pLineRef->maPhClr.getSchemeName())},
979                     {"Idx", uno::makeAny(pLineRef->mnThemedIdx)},
980                     {"Color", uno::makeAny(nLinePhClr)},
981                     {"LineStyle", uno::makeAny(aLineProperties.getLineStyle())},
982                     {"LineCap", uno::makeAny(aLineProperties.getLineCap())},
983                     {"LineJoint", uno::makeAny(aLineProperties.getLineJoint())},
984                     {"LineWidth", uno::makeAny(aLineProperties.getLineWidth())},
985                     {"Transformations", uno::makeAny(pLineRef->maPhClr.getTransformations())}
986                 });
987                 putPropertyToGrabBag( "StyleLnRef", Any( aProperties ) );
988             }
989             if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) )
990             {
991                 if (!mbUseBgFill)
992                 {
993                     nFillPhClr = pFillRef->maPhClr.getColor(rGraphicHelper);
994                 }
995 
996                 OUString sColorScheme = pFillRef->maPhClr.getSchemeName();
997                 if( !sColorScheme.isEmpty() )
998                 {
999                     uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
1000                     {
1001                         {"SchemeClr", uno::makeAny(sColorScheme)},
1002                         {"Idx", uno::makeAny(pFillRef->mnThemedIdx)},
1003                         {"Color", uno::makeAny(nFillPhClr)},
1004                         {"Transformations", uno::makeAny(pFillRef->maPhClr.getTransformations())}
1005                     });
1006 
1007                     putPropertyToGrabBag( "StyleFillRef", Any( aProperties ) );
1008                 }
1009             }
1010             if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) )
1011             {
1012                 // TODO: use ph color when applying effect properties
1013                 // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper );
1014 
1015                 // Store style-related properties to InteropGrabBag to be able to export them back
1016                 uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
1017                 {
1018                     {"SchemeClr", uno::makeAny(pEffectRef->maPhClr.getSchemeName())},
1019                     {"Idx", uno::makeAny(pEffectRef->mnThemedIdx)},
1020                     {"Transformations", uno::makeAny(pEffectRef->maPhClr.getTransformations())}
1021                 });
1022                 putPropertyToGrabBag( "StyleEffectRef", Any( aProperties ) );
1023             }
1024         }
1025         ShapePropertyMap aShapeProps( rFilterBase.getModelObjectHelper() );
1026 
1027         // add properties from textbody to shape properties
1028         if( mpTextBody.get() )
1029         {
1030             mpTextBody->getTextProperties().pushRotationAdjustments();
1031             aShapeProps.assignUsed( mpTextBody->getTextProperties().maPropertyMap );
1032             // Push char properties as well - specifically useful when this is a placeholder
1033             if( mpMasterTextListStyle &&  mpMasterTextListStyle->getListStyle()[0]->getTextCharacterProperties().moHeight.has() )
1034                 aShapeProps.setProperty(PROP_CharHeight, GetFontHeight( mpMasterTextListStyle->getListStyle()[0]->getTextCharacterProperties().moHeight.get() ));
1035         }
1036 
1037         // applying properties
1038         aShapeProps.assignUsed( getShapeProperties() );
1039         aShapeProps.assignUsed( maDefaultShapeProperties );
1040         if ( bIsEmbMedia || aServiceName == "com.sun.star.drawing.GraphicObjectShape" || aServiceName == "com.sun.star.drawing.OLE2Shape" || bIsCustomShape )
1041             mpGraphicPropertiesPtr->pushToPropMap( aShapeProps, rGraphicHelper );
1042         if ( mpTablePropertiesPtr.get() && aServiceName == "com.sun.star.drawing.TableShape" )
1043             mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle );
1044 
1045         FillProperties aFillProperties = getActualFillProperties(pTheme, &rShapeOrParentShapeFillProps);
1046         if(!bIsCroppedGraphic)
1047             aFillProperties.pushToPropMap( aShapeProps, rGraphicHelper, mnRotation, nFillPhClr, mbFlipH, mbFlipV );
1048         LineProperties aLineProperties = getActualLineProperties(pTheme);
1049         aLineProperties.pushToPropMap( aShapeProps, rGraphicHelper, nLinePhClr );
1050         EffectProperties aEffectProperties = getActualEffectProperties(pTheme);
1051         // TODO: use ph color when applying effect properties
1052         aEffectProperties.pushToPropMap( aShapeProps, rGraphicHelper );
1053 
1054         // applying autogrowheight property before setting shape size, because
1055         // the shape size might be changed if currently autogrowheight is true
1056         // we must also check that the PropertySet supports the property.
1057         Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1058         const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight );
1059         if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) )
1060             if( aShapeProps.hasProperty( PROP_TextAutoGrowHeight ) )
1061                 xSet->setPropertyValue( rPropName, Any( false ) );
1062 
1063         // do not set properties at a group shape (this causes
1064         // assertions from svx) ...
1065         if( aServiceName != "com.sun.star.drawing.GroupShape" )
1066         {
1067             if (aServiceName == "com.sun.star.text.TextFrame")
1068             {
1069                 if (mpCustomShapePropertiesPtr && mpCustomShapePropertiesPtr->getShapeTypeOverride())
1070                 {
1071                     uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1072                     uno::Sequence<beans::PropertyValue> aGrabBag;
1073                     propertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
1074                     sal_Int32 length = aGrabBag.getLength();
1075                     aGrabBag.realloc( length+1);
1076                     aGrabBag[length].Name = "mso-orig-shape-type";
1077                     uno::Sequence< sal_Int8 > const & aNameSeq =
1078                         mpCustomShapePropertiesPtr->getShapePresetTypeName();
1079                     OUString sShapePresetTypeName(reinterpret_cast< const char* >(
1080                         aNameSeq.getConstArray()), aNameSeq.getLength(), RTL_TEXTENCODING_UTF8);
1081                     aGrabBag[length].Value <<= sShapePresetTypeName;
1082                     propertySet->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aGrabBag));
1083                 }
1084                 //If the text box has links then save the link information so that
1085                 //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames.
1086                 if (isLinkedTxbx())
1087                 {
1088                     uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1089                     uno::Sequence<beans::PropertyValue> aGrabBag;
1090                     propertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
1091                     sal_Int32 length = aGrabBag.getLength();
1092                     aGrabBag.realloc( length + 3 );
1093                     aGrabBag[length].Name = "TxbxHasLink";
1094                     aGrabBag[length].Value <<= isLinkedTxbx();
1095                     aGrabBag[length + 1 ].Name = "Txbx-Id";
1096                     aGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id;
1097                     aGrabBag[length + 2 ].Name = "Txbx-Seq";
1098                     aGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq;
1099                     propertySet->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aGrabBag));
1100                 }
1101 
1102                 // TextFrames have BackColor, not FillColor
1103                 if (aShapeProps.hasProperty(PROP_FillColor))
1104                 {
1105                     aShapeProps.setAnyProperty(PROP_BackColor, aShapeProps.getProperty(PROP_FillColor));
1106                     aShapeProps.erase(PROP_FillColor);
1107                 }
1108                 // TextFrames have BackColorTransparency, not FillTransparence
1109                 if (aShapeProps.hasProperty(PROP_FillTransparence))
1110                 {
1111                     aShapeProps.setAnyProperty(PROP_BackColorTransparency, aShapeProps.getProperty(PROP_FillTransparence));
1112                     aShapeProps.erase(PROP_FillTransparence);
1113                 }
1114                 // TextFrames have BackGraphic, not FillBitmap
1115                 if (aShapeProps.hasProperty(PROP_FillBitmap))
1116                 {
1117                     aShapeProps.setAnyProperty(PROP_BackGraphic, aShapeProps.getProperty(PROP_FillBitmap));
1118                     aShapeProps.erase(PROP_FillBitmap);
1119                 }
1120                 if (aShapeProps.hasProperty(PROP_FillBitmapName))
1121                 {
1122                     uno::Any aAny = aShapeProps.getProperty(PROP_FillBitmapName);
1123                     OUString aFillBitmapName = aAny.get<OUString>();
1124                     uno::Reference<awt::XBitmap> xBitmap = rFilterBase.getModelObjectHelper().getFillBitmap(aFillBitmapName);
1125                     uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
1126                     aShapeProps.setProperty(PROP_BackGraphic, xGraphic);
1127                     // aShapeProps.erase(PROP_FillBitmapName);  // Maybe, leave the name as well
1128                 }
1129                 // And no LineColor property; individual borders can have colors
1130                 if (aShapeProps.hasProperty(PROP_LineColor))
1131                 {
1132                     uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
1133                     static const sal_Int32 aBorders[] =
1134                     {
1135                         PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder
1136                     };
1137                     for (sal_Int32 nBorder : aBorders)
1138                     {
1139                         css::table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(nBorder)).get<css::table::BorderLine2>();
1140                         aBorderLine.Color = aShapeProps.getProperty(PROP_LineColor).get<sal_Int32>();
1141                         if (aLineProperties.moLineWidth.has())
1142                             aBorderLine.LineWidth = convertEmuToHmm(aLineProperties.moLineWidth.get());
1143                         aShapeProps.setProperty(nBorder, aBorderLine);
1144                     }
1145                     aShapeProps.erase(PROP_LineColor);
1146                 }
1147                 if(mnRotation)
1148                 {
1149                     uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
1150                     const OUString aGrabBagPropName = "FrameInteropGrabBag";
1151                     uno::Sequence<beans::PropertyValue> aGrabBag;
1152                     xPropertySet->getPropertyValue(aGrabBagPropName) >>= aGrabBag;
1153                     beans::PropertyValue aPair;
1154                     aPair.Name = "mso-rotation-angle";
1155                     aPair.Value <<= mnRotation;
1156                     if (aGrabBag.hasElements())
1157                     {
1158                         sal_Int32 nLength = aGrabBag.getLength();
1159                         aGrabBag.realloc(nLength + 1);
1160                         aGrabBag[nLength] = aPair;
1161                     }
1162                     else
1163                     {
1164                         aGrabBag.realloc(1);
1165                         aGrabBag[0] = aPair;
1166                     }
1167                     xPropertySet->setPropertyValue(aGrabBagPropName, uno::makeAny(aGrabBag));
1168                 }
1169                 // TextFrames have ShadowFormat, not individual shadow properties.
1170                 boost::optional<sal_Int32> oShadowDistance;
1171                 if (aShapeProps.hasProperty(PROP_ShadowXDistance))
1172                 {
1173                     oShadowDistance = aShapeProps.getProperty(PROP_ShadowXDistance).get<sal_Int32>();
1174                     aShapeProps.erase(PROP_ShadowXDistance);
1175                 }
1176                 if (aShapeProps.hasProperty(PROP_ShadowYDistance))
1177                 {
1178                     // There is a single 'dist' attribute, so no need to count the avg of x and y.
1179                     aShapeProps.erase(PROP_ShadowYDistance);
1180                 }
1181                 boost::optional<sal_Int32> oShadowColor;
1182                 if (aShapeProps.hasProperty(PROP_ShadowColor))
1183                 {
1184                     oShadowColor = aShapeProps.getProperty(PROP_ShadowColor).get<sal_Int32>();
1185                     aShapeProps.erase(PROP_ShadowColor);
1186                 }
1187                 if (aShapeProps.hasProperty(PROP_Shadow))
1188                     aShapeProps.erase(PROP_Shadow);
1189 
1190                 if (oShadowDistance || oShadowColor || aEffectProperties.maShadow.moShadowDir.has())
1191                 {
1192                     css::table::ShadowFormat aFormat;
1193                     if (oShadowColor)
1194                         aFormat.Color = *oShadowColor;
1195                     if (aEffectProperties.maShadow.moShadowDir.has())
1196                     {
1197                         css::table::ShadowLocation nLocation = css::table::ShadowLocation_NONE;
1198                         switch (aEffectProperties.maShadow.moShadowDir.get())
1199                         {
1200                         case 13500000:
1201                             nLocation = css::table::ShadowLocation_TOP_LEFT;
1202                             break;
1203                         case 18900000:
1204                             nLocation = css::table::ShadowLocation_TOP_RIGHT;
1205                             break;
1206                         case 8100000:
1207                             nLocation = css::table::ShadowLocation_BOTTOM_LEFT;
1208                             break;
1209                         case 2700000:
1210                             nLocation = css::table::ShadowLocation_BOTTOM_RIGHT;
1211                             break;
1212                         }
1213                         aFormat.Location = nLocation;
1214                     }
1215                     aFormat.ShadowWidth = *oShadowDistance;
1216                     aShapeProps.setProperty(PROP_ShadowFormat, aFormat);
1217                 }
1218             }
1219             else if (mbTextBox)
1220             {
1221                 aShapeProps.setProperty(PROP_TextBox, true);
1222             }
1223 
1224             if (aServiceName != "com.sun.star.text.TextFrame" && isLinkedTxbx())
1225             {
1226                 uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1227                 uno::Sequence<beans::PropertyValue> aGrabBag;
1228                 propertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
1229                 sal_Int32 length = aGrabBag.getLength();
1230                 aGrabBag.realloc( length + 3 );
1231                 aGrabBag[length].Name = "TxbxHasLink";
1232                 aGrabBag[length].Value <<= isLinkedTxbx();
1233                 aGrabBag[length + 1 ].Name = "Txbx-Id";
1234                 aGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id;
1235                 aGrabBag[length + 2 ].Name = "Txbx-Seq";
1236                 aGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq;
1237                 propertySet->setPropertyValue("InteropGrabBag",uno::makeAny(aGrabBag));
1238             }
1239 
1240             PropertySet( xSet ).setProperties( aShapeProps );
1241             if (mbLockedCanvas)
1242             {
1243                 putPropertyToGrabBag( "LockedCanvas", Any( true ) );
1244                 if (aServiceName == "com.sun.star.drawing.LineShape")
1245                 {
1246                     // It seems the position and size for lines inside a locked canvas is absolute.
1247                     mxShape->setPosition(awt::Point(aShapeRectHmm.X, aShapeRectHmm.Y));
1248                     mxShape->setSize(awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height));
1249                 }
1250             }
1251 
1252             // Store original fill and line colors of the shape and the theme color name to InteropGrabBag
1253             std::vector<beans::PropertyValue> aProperties;
1254             aProperties.push_back(comphelper::makePropertyValue("OriginalSolidFillClr", aShapeProps.getProperty(PROP_FillColor)));
1255             aProperties.push_back(comphelper::makePropertyValue("OriginalLnSolidFillClr", aShapeProps.getProperty(PROP_LineColor)));
1256             OUString sColorFillScheme = aFillProperties.maFillColor.getSchemeName();
1257             if( !aFillProperties.maFillColor.isPlaceHolder() && !sColorFillScheme.isEmpty() )
1258             {
1259                 aProperties.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClr", sColorFillScheme));
1260                 aProperties.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClrTransformations", aFillProperties.maFillColor.getTransformations()));
1261             }
1262             OUString sLnColorFillScheme = aLineProperties.maLineFill.maFillColor.getSchemeName();
1263             if( !aLineProperties.maLineFill.maFillColor.isPlaceHolder() && !sLnColorFillScheme.isEmpty() )
1264             {
1265                 aProperties.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClr", sLnColorFillScheme));
1266                 aProperties.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClrTransformations", aLineProperties.maLineFill.maFillColor.getTransformations()));
1267             }
1268             putPropertiesToGrabBag(comphelper::containerToSequence(aProperties));
1269 
1270             // Store original gradient fill of the shape to InteropGrabBag
1271             // LibreOffice doesn't support all the kinds of gradient so we save its complete definition
1272             if( aShapeProps.hasProperty( PROP_FillGradient ) )
1273             {
1274                 std::vector<beans::PropertyValue> aGradientStops;
1275                 size_t i = 0;
1276                 for( const auto& [rPos, rColor] : aFillProperties.maGradientProps.maGradientStops )
1277                 { // for each stop in the gradient definition:
1278 
1279                     // save position
1280                     std::vector<beans::PropertyValue> aGradientStop;
1281                     aGradientStop.push_back(comphelper::makePropertyValue("Pos", rPos));
1282 
1283                     OUString sStopColorScheme = rColor.getSchemeName();
1284                     if( sStopColorScheme.isEmpty() )
1285                     {
1286                         // save RGB color
1287                         aGradientStop.push_back(comphelper::makePropertyValue("RgbClr", rColor.getColor(rGraphicHelper, nFillPhClr)));
1288                         // in the case of a RGB color, transformations are already applied to
1289                         // the color with the exception of alpha transformations. We only need
1290                         // to keep the transparency value to calculate the alpha value later.
1291                         if( rColor.hasTransparency() )
1292                             aGradientStop.push_back(comphelper::makePropertyValue("Transparency", rColor.getTransparency()));
1293                     }
1294                     else
1295                     {
1296                         // save color with scheme name
1297                         aGradientStop.push_back(comphelper::makePropertyValue("SchemeClr", sStopColorScheme));
1298                         // save all color transformations
1299                         aGradientStop.push_back(comphelper::makePropertyValue("Transformations", rColor.getTransformations()));
1300                     }
1301 
1302                     aGradientStops.push_back(comphelper::makePropertyValue(OUString::number(i), comphelper::containerToSequence(aGradientStop)));
1303                     ++i;
1304                 }
1305                 // If getFillProperties.moFillType is unused that means gradient is defined by a theme
1306                 // which is already saved into StyleFillRef property, so no need to save the explicit values too
1307                 if( getFillProperties().moFillType.has() )
1308                     putPropertyToGrabBag( "GradFillDefinition", uno::Any(comphelper::containerToSequence(aGradientStops)));
1309                 putPropertyToGrabBag( "OriginalGradFill", aShapeProps.getProperty(PROP_FillGradient) );
1310             }
1311 
1312             // store unsupported effect attributes in the grab bag
1313             if (!aEffectProperties.m_Effects.empty())
1314             {
1315                 std::vector<beans::PropertyValue> aEffects;
1316                 sal_uInt32 i = 0;
1317                 for (auto const& it : aEffectProperties.m_Effects)
1318                 {
1319                     PropertyValue aEffect = it->getEffect();
1320                     if( !aEffect.Name.isEmpty() )
1321                     {
1322                         std::vector<beans::PropertyValue> aEffectsGrabBag;
1323                         aEffectsGrabBag.push_back(comphelper::makePropertyValue("Attribs", aEffect.Value));
1324 
1325                         Color& aColor( it->moColor );
1326                         OUString sColorScheme = aColor.getSchemeName();
1327                         if( sColorScheme.isEmpty() )
1328                         {
1329                             // RGB color and transparency value
1330                             aEffectsGrabBag.push_back(comphelper::makePropertyValue("RgbClr", aColor.getColor(rGraphicHelper, nFillPhClr)));
1331                             aEffectsGrabBag.push_back(comphelper::makePropertyValue("RgbClrTransparency", aColor.getTransparency()));
1332                         }
1333                         else
1334                         {
1335                             // scheme color with name and transformations
1336                             aEffectsGrabBag.push_back(comphelper::makePropertyValue("SchemeClr", sColorScheme));
1337                             aEffectsGrabBag.push_back(comphelper::makePropertyValue("SchemeClrTransformations", aColor.getTransformations()));
1338                         }
1339                         aEffects.push_back(comphelper::makePropertyValue(aEffect.Name, comphelper::containerToSequence(aEffectsGrabBag)));
1340                         ++i;
1341                     }
1342                 }
1343                 putPropertyToGrabBag("EffectProperties", uno::Any(comphelper::containerToSequence(aEffects)));
1344             }
1345 
1346             // add 3D effects if any
1347             Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes();
1348             Sequence< PropertyValue > aLightRig3DEffects = get3DProperties().getLightRigAttributes();
1349             Sequence< PropertyValue > aShape3DEffects = get3DProperties().getShape3DAttributes( rGraphicHelper, nFillPhClr );
1350             if( aCamera3DEffects.hasElements() || aLightRig3DEffects.hasElements() || aShape3DEffects.hasElements() )
1351             {
1352                 uno::Sequence<beans::PropertyValue> a3DEffectsGrabBag = comphelper::InitPropertySequence(
1353                 {
1354                     {"Camera", uno::makeAny(aCamera3DEffects)},
1355                     {"LightRig", uno::makeAny(aLightRig3DEffects)},
1356                     {"Shape3D", uno::makeAny(aShape3DEffects)}
1357                 });
1358                 putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag ) );
1359             }
1360 
1361             // store bitmap artistic effects in the grab bag
1362             if( !mpGraphicPropertiesPtr->maBlipProps.maEffect.isEmpty() )
1363                 putPropertyToGrabBag( "ArtisticEffectProperties",
1364                                       Any( mpGraphicPropertiesPtr->maBlipProps.maEffect.getEffect() ) );
1365         }
1366 
1367         else if( mbLockedCanvas )
1368         {
1369             //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas
1370             putPropertyToGrabBag( "LockedCanvas", Any( true ) );
1371         }
1372 
1373         // These can have a custom geometry, so position should be set here,
1374         // after creation but before custom shape handling, using the position
1375         // we got from the caller.
1376         if (mbWps && aServiceName == "com.sun.star.drawing.LineShape")
1377             mxShape->setPosition(maPosition);
1378 
1379         if( bIsCustomShape )
1380         {
1381             if ( mbFlipH )
1382                 mpCustomShapePropertiesPtr->setMirroredX( true );
1383             if ( mbFlipV )
1384                 mpCustomShapePropertiesPtr->setMirroredY( true );
1385             if( getTextBody() )
1386             {
1387                 sal_Int32 nTextCameraZRotation = static_cast< sal_Int32 >( get3DProperties().maCameraRotation.mnRevolution.get() );
1388                 mpCustomShapePropertiesPtr->setTextCameraZRotateAngle( nTextCameraZRotation / 60000 );
1389 
1390                 sal_Int32 nTextRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moRotation.get( 0 ) );
1391 
1392                 nTextRotateAngle -= mnDiagramRotation;
1393                 /* OOX measures text rotation clockwise in 1/60000th degrees,
1394                    relative to the containing shape. setTextRotateAngle wants
1395                    degrees anticlockwise. */
1396                 mpCustomShapePropertiesPtr->setTextRotateAngle( -1 * nTextRotateAngle / 60000 );
1397             }
1398 
1399             // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks
1400             // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs
1401             SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName << "'");
1402             SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName << "'");
1403             mpCustomShapePropertiesPtr->pushToPropSet( xSet, mxShape, maSize );
1404 
1405             if (mpTextBody)
1406             {
1407                 bool bIsPresetShape = !mpTextBody->getTextProperties().msPrst.isEmpty();
1408                 if (bIsPresetShape)
1409                 {
1410                     OUString sClass;
1411                     const OUString sPresetType = mpTextBody->getTextProperties().msPrst;
1412                     sClass = PresetGeometryTypeNames::GetFontworkType( sPresetType );
1413 
1414                     lcl_createPresetShape( mxShape, sClass, sPresetType, mpCustomShapePropertiesPtr, mpTextBody, rGraphicHelper );
1415                 }
1416             }
1417         }
1418         else if( getTextBody() )
1419             getTextBody()->getTextProperties().pushVertSimulation();
1420 
1421         PropertySet aPropertySet(mxShape);
1422         if ( !bUseRotationTransform && mnRotation != 0 )
1423         {
1424             // use the same logic for rotation from VML exporter (SimpleShape::implConvertAndInsert at vmlshape.cxx)
1425             aPropertySet.setAnyProperty( PROP_RotateAngle, makeAny( sal_Int32( NormAngle36000( mnRotation / -600 ) ) ) );
1426             aPropertySet.setAnyProperty( PROP_HoriOrientPosition, makeAny( maPosition.X ) );
1427             aPropertySet.setAnyProperty( PROP_VertOrientPosition, makeAny( maPosition.Y ) );
1428         }
1429 
1430         // in some cases, we don't have any text body.
1431         if( getTextBody() && ( !bDoNotInsertEmptyTextBody || !mpTextBody->isEmpty() ) )
1432         {
1433             Reference < XText > xText( mxShape, UNO_QUERY );
1434             if ( xText.is() )   // not every shape is supporting an XText interface (e.g. GroupShape)
1435             {
1436                 TextCharacterProperties aCharStyleProperties;
1437                 if( const ShapeStyleRef* pFontRef = getShapeStyleRef( XML_fontRef ) )
1438                 {
1439                     if( pFontRef->mnThemedIdx != 0 )
1440                     {
1441                         if( pTheme )
1442                             if( const TextCharacterProperties* pCharProps = pTheme->getFontStyle( pFontRef->mnThemedIdx ) )
1443                                 aCharStyleProperties.assignUsed( *pCharProps );
1444                         SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color");
1445                         if ( pFontRef->maPhClr.isUsed() )
1446                         {
1447                             aCharStyleProperties.maFillProperties.maFillColor = pFontRef->maPhClr;
1448                             aCharStyleProperties.maFillProperties.moFillType.set(XML_solidFill);
1449                         }
1450                     }
1451                 }
1452                 xText->setString("");
1453                 Reference < XTextCursor > xAt = xText->createTextCursor();
1454                 getTextBody()->insertAt( rFilterBase, xText, xAt, aCharStyleProperties, mpMasterTextListStyle );
1455 
1456                 const TextParagraphVector& rParagraphs = getTextBody()->getParagraphs();
1457                 if (!rParagraphs.empty())
1458                 {
1459                     const std::shared_ptr<TextParagraph>& pParagraph = rParagraphs[0];
1460                     if (pParagraph->getProperties().getParaAdjust())
1461                     {
1462                         style::ParagraphAdjust eAdjust = *pParagraph->getProperties().getParaAdjust();
1463                         if (eAdjust == style::ParagraphAdjust_CENTER)
1464                         {
1465                             // If the first paragraph is centered, then set the para adjustment of
1466                             // the shape itself to centered as well.
1467                             aPropertySet.setAnyProperty(PROP_ParaAdjust, uno::makeAny(eAdjust));
1468                         }
1469                     }
1470                 }
1471             }
1472         }
1473         else if (mbTextBox)
1474         {
1475             // No drawingML text, but WPS text is expected: save the theme
1476             // character color on the shape, then.
1477             if(const ShapeStyleRef* pFontRef = getShapeStyleRef(XML_fontRef))
1478             {
1479                 ::Color nCharColor = pFontRef->maPhClr.getColor(rGraphicHelper);
1480                 aPropertySet.setAnyProperty(PROP_CharColor, uno::makeAny(nCharColor));
1481             }
1482         }
1483     }
1484 
1485     if( mxShape.is() )
1486         finalizeXShape( rFilterBase, rxShapes );
1487 
1488     return mxShape;
1489 }
1490 
keepDiagramDrawing(XmlFilterBase & rFilterBase,const OUString & rFragmentPath)1491 void Shape::keepDiagramDrawing(XmlFilterBase& rFilterBase, const OUString& rFragmentPath)
1492 {
1493     uno::Sequence<uno::Any> diagramDrawing(2);
1494     // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships
1495 
1496     sal_Int32 length = maDiagramDoms.getLength();
1497     maDiagramDoms.realloc(length + 1);
1498 
1499     diagramDrawing[0] <<= rFilterBase.importFragment(rFragmentPath);
1500     diagramDrawing[1] <<= resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, "image");
1501 
1502     beans::PropertyValue* pValue = maDiagramDoms.getArray();
1503     pValue[length].Name = "OOXDrawing";
1504     pValue[length].Value <<= diagramDrawing;
1505 }
1506 
keepDiagramCompatibilityInfo()1507 void Shape::keepDiagramCompatibilityInfo()
1508 {
1509     try
1510     {
1511         if( !maDiagramDoms.hasElements() )
1512             return;
1513 
1514         Reference < XPropertySet > xSet( mxShape, UNO_QUERY_THROW );
1515         Reference < XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1516         if ( !xSetInfo.is() )
1517             return;
1518 
1519         if (mpDiagramData)
1520         {
1521             if (SdrObject* pObj = GetSdrObjectFromXShape(mxShape))
1522                 pObj->SetDiagramData(mpDiagramData);
1523         }
1524 
1525         const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1526         if( !xSetInfo->hasPropertyByName( aGrabBagPropName ) )
1527             return;
1528 
1529         Sequence < PropertyValue > aGrabBag;
1530         xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
1531 
1532         // We keep the previous items, if present
1533         if ( aGrabBag.hasElements() )
1534             xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, maDiagramDoms) ) );
1535         else
1536             xSet->setPropertyValue( aGrabBagPropName, Any( maDiagramDoms ) );
1537     }
1538     catch( const Exception& )
1539     {
1540         TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::keepDiagramCompatibilityInfo" );
1541     }
1542 }
1543 
convertSmartArtToMetafile(XmlFilterBase const & rFilterBase)1544 void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase)
1545 {
1546     try
1547     {
1548         Reference<XPropertySet> xSet(mxShape, UNO_QUERY_THROW);
1549 
1550         xSet->setPropertyValue("MoveProtect", Any(true));
1551         xSet->setPropertyValue("SizeProtect", Any(true));
1552 
1553         // Replace existing shapes with a new Graphic Object rendered
1554         // from them
1555         Reference<XShape> xShape(renderDiagramToGraphic(rFilterBase));
1556         Reference<XShapes> xShapes(mxShape, UNO_QUERY_THROW);
1557         while (xShapes->hasElements())
1558             xShapes->remove(Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW));
1559         xShapes->add(xShape);
1560     }
1561     catch (const Exception&)
1562     {
1563         TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile");
1564     }
1565 }
1566 
renderDiagramToGraphic(XmlFilterBase const & rFilterBase)1567 Reference < XShape > Shape::renderDiagramToGraphic( XmlFilterBase const & rFilterBase )
1568 {
1569     Reference< XShape > xShape;
1570 
1571     try
1572     {
1573         if( !maDiagramDoms.hasElements() )
1574             return xShape;
1575 
1576         // Stream in which to place the rendered shape
1577         SvMemoryStream aTempStream;
1578         Reference < io::XStream > xStream( new utl::OStreamWrapper( aTempStream ) );
1579         Reference < io::XOutputStream > xOutputStream( xStream->getOutputStream() );
1580 
1581         // Size of the rendering
1582         awt::Size aActualSize = mxShape->getSize();
1583         Size aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM)));
1584         double fPixelsPer100thmm = static_cast < double > ( aResolution.Width() ) / 100000.0;
1585         awt::Size aSize( static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Width ) + 0.5 ),
1586                          static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Height ) + 0.5 ) );
1587 
1588         Sequence< PropertyValue > aFilterData( 4 );
1589         aFilterData[ 0 ].Name = "PixelWidth";
1590         aFilterData[ 0 ].Value <<= aSize.Width;
1591         aFilterData[ 1 ].Name = "PixelHeight";
1592         aFilterData[ 1 ].Value <<= aSize.Height;
1593         aFilterData[ 2 ].Name = "LogicalWidth";
1594         aFilterData[ 2 ].Value <<= aActualSize.Width;
1595         aFilterData[ 3 ].Name = "LogicalHeight";
1596         aFilterData[ 3 ].Value <<= aActualSize.Height;
1597 
1598         Sequence < PropertyValue > aDescriptor( 3 );
1599         aDescriptor[ 0 ].Name = "OutputStream";
1600         aDescriptor[ 0 ].Value <<= xOutputStream;
1601         aDescriptor[ 1 ].Name = "FilterName";
1602         aDescriptor[ 1 ].Value <<= OUString("SVM"); // Rendering format
1603         aDescriptor[ 2 ].Name = "FilterData";
1604         aDescriptor[ 2 ].Value <<= aFilterData;
1605 
1606         Reference < lang::XComponent > xSourceDoc( mxShape, UNO_QUERY_THROW );
1607         Reference < XGraphicExportFilter > xGraphicExporter = GraphicExportFilter::create( rFilterBase.getComponentContext() );
1608         xGraphicExporter->setSourceDocument( xSourceDoc );
1609         xGraphicExporter->filter( aDescriptor );
1610 
1611         aTempStream.Seek( STREAM_SEEK_TO_BEGIN );
1612 
1613         Graphic aGraphic;
1614         GraphicFilter aFilter( false );
1615         if ( aFilter.ImportGraphic( aGraphic, "", aTempStream, GRFILTER_FORMAT_NOTFOUND, nullptr, GraphicFilterImportFlags::NONE, static_cast < Sequence < PropertyValue >* > ( nullptr ) ) != ERRCODE_NONE )
1616         {
1617             SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" );
1618             return xShape;
1619         }
1620 
1621         Reference < graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
1622         Reference < lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
1623         xShape.set( xServiceFact->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), UNO_QUERY_THROW );
1624         Reference < XPropertySet > xPropSet( xShape, UNO_QUERY_THROW );
1625         xPropSet->setPropertyValue(  "Graphic", Any( xGraphic ) );
1626         xPropSet->setPropertyValue(  "MoveProtect", Any( true ) );
1627         xPropSet->setPropertyValue(  "SizeProtect", Any( true ) );
1628         xPropSet->setPropertyValue(  "Name", Any( OUString( "RenderedShapes" ) ) );
1629     }
1630     catch( const Exception& )
1631     {
1632         TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" );
1633     }
1634 
1635     return xShape;
1636 }
1637 
setTextBody(const TextBodyPtr & pTextBody)1638 void Shape::setTextBody(const TextBodyPtr & pTextBody)
1639 {
1640     mpTextBody = pTextBody;
1641 }
1642 
setMasterTextListStyle(const TextListStylePtr & pMasterTextListStyle)1643 void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle )
1644 {
1645     SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId << "'");
1646 
1647     mpMasterTextListStyle = pMasterTextListStyle;
1648 }
1649 
finalizeServiceName(XmlFilterBase & rFilter,const OUString & rServiceName,const awt::Rectangle & rShapeRect)1650 OUString Shape::finalizeServiceName( XmlFilterBase& rFilter, const OUString& rServiceName, const awt::Rectangle& rShapeRect )
1651 {
1652     OUString aServiceName = rServiceName;
1653     switch( meFrameType )
1654     {
1655         case FRAMETYPE_OLEOBJECT:
1656         {
1657             awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height );
1658             if( rFilter.getOleObjectHelper().importOleObject( maShapeProperties, *mxOleObjectInfo, aOleSize ) )
1659                 aServiceName = "com.sun.star.drawing.OLE2Shape";
1660 
1661             // get the path to the representation graphic
1662             OUString aGraphicPath;
1663             if( !mxOleObjectInfo->maShapeId.isEmpty() )
1664                 if( ::oox::vml::Drawing* pVmlDrawing = rFilter.getVmlDrawing() )
1665                     if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId ) )
1666                         aGraphicPath = pVmlShape->getGraphicPath();
1667 
1668             // import and store the graphic
1669             if( !aGraphicPath.isEmpty() )
1670             {
1671                 // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF)
1672                 WmfExternal aExtHeader;
1673                 aExtHeader.mapMode = 8; // MM_ANISOTROPIC
1674                 aExtHeader.xExt = rShapeRect.Width;
1675                 aExtHeader.yExt = rShapeRect.Height;
1676 
1677                 Reference< graphic::XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath, &aExtHeader );
1678                 if( xGraphic.is() )
1679                     maShapeProperties.setProperty(PROP_Graphic, xGraphic);
1680             }
1681         }
1682         break;
1683 
1684         default:;
1685     }
1686     return aServiceName;
1687 }
1688 
finalizeXShape(XmlFilterBase & rFilter,const Reference<XShapes> & rxShapes)1689 void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes )
1690 {
1691     switch( meFrameType )
1692     {
1693         case FRAMETYPE_CHART:
1694         {
1695             OSL_ENSURE( !mxChartShapeInfo->maFragmentPath.isEmpty(), "Shape::finalizeXShape - missing chart fragment" );
1696             if( mxShape.is() && !mxChartShapeInfo->maFragmentPath.isEmpty() ) try
1697             {
1698                 // set the chart2 OLE class ID at the OLE shape
1699                 PropertySet aShapeProp( mxShape );
1700                 aShapeProp.setProperty( PROP_CLSID, OUString( "12dcae26-281f-416f-a234-c3086127382e" ) );
1701 
1702                 // get the XModel interface of the embedded object from the OLE shape
1703                 Reference< frame::XModel > xDocModel;
1704                 aShapeProp.getProperty( xDocModel, PROP_Model );
1705                 Reference< chart2::XChartDocument > xChartDoc( xDocModel, UNO_QUERY_THROW );
1706 
1707                 // load the chart data from the XML fragment
1708                 bool bMSO2007Doc = rFilter.isMSO2007Document();
1709                 chart::ChartSpaceModel aModel(bMSO2007Doc);
1710                 chart::ChartSpaceFragment *pChartSpaceFragment = new chart::ChartSpaceFragment(
1711                         rFilter, mxChartShapeInfo->maFragmentPath, aModel );
1712                 const OUString aThemeOverrideFragmentPath( pChartSpaceFragment->
1713                         getFragmentPathFromFirstTypeFromOfficeDoc("themeOverride") );
1714                 rFilter.importFragment( pChartSpaceFragment );
1715                 ::oox::ppt::PowerPointImport *pPowerPointImport =
1716                     dynamic_cast< ::oox::ppt::PowerPointImport* >(&rFilter);
1717                 if (!aThemeOverrideFragmentPath.isEmpty() && pPowerPointImport)
1718                 {
1719                     uno::Reference< xml::sax::XFastSAXSerializable > xDoc(
1720                             rFilter.importFragment(aThemeOverrideFragmentPath), uno::UNO_QUERY_THROW);
1721                     ThemePtr pTheme = pPowerPointImport->getActualSlidePersist()->getTheme();
1722                     rFilter.importFragment(new ThemeOverrideFragmentHandler(
1723                                 rFilter, aThemeOverrideFragmentPath, *pTheme), xDoc);
1724                     pPowerPointImport->getActualSlidePersist()->setTheme(pTheme);
1725                 }
1726 
1727                 // convert imported chart model to chart document
1728                 Reference< drawing::XShapes > xExternalPage;
1729                 if( !mxChartShapeInfo->mbEmbedShapes )
1730                     xExternalPage = rxShapes;
1731                 if( rFilter.getChartConverter() )
1732                 {
1733                     rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() );
1734                     if( !xChartDoc->hasInternalDataProvider() )
1735                     {
1736                         Reference< chart2::data::XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
1737                         Reference< chart2::data::XDataSource > xData = xDataRec->getUsedData();
1738                         if( !xData->getDataSequences().hasElements() || !xData->getDataSequences()[0]->getValues().is() ||
1739                                 !xData->getDataSequences()[0]->getValues()->getData().hasElements() )
1740                         {
1741                             rFilter.useInternalChartDataTable( true );
1742                             rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() );
1743                             rFilter.useInternalChartDataTable( false );
1744                         }
1745                     }
1746 
1747                 }
1748             }
1749             catch( Exception& )
1750             {
1751             }
1752         }
1753         break;
1754 
1755         default:;
1756     }
1757 }
1758 
putPropertyToGrabBag(const OUString & sPropertyName,const Any & aPropertyValue)1759 void Shape::putPropertyToGrabBag( const OUString& sPropertyName, const Any& aPropertyValue )
1760 {
1761     PropertyValue aNewProperty;
1762     aNewProperty.Name = sPropertyName;
1763     aNewProperty.Value = aPropertyValue;
1764     putPropertyToGrabBag( aNewProperty );
1765 }
1766 
putPropertyToGrabBag(const PropertyValue & pProperty)1767 void Shape::putPropertyToGrabBag( const PropertyValue& pProperty )
1768 {
1769     Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
1770     Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1771     const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1772     if( mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName ) )
1773     {
1774         Sequence< PropertyValue > aGrabBag;
1775         xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
1776 
1777         sal_Int32 length = aGrabBag.getLength();
1778         aGrabBag.realloc( length + 1 );
1779         aGrabBag[length] = pProperty;
1780 
1781         xSet->setPropertyValue( aGrabBagPropName, Any( aGrabBag ) );
1782     }
1783 }
1784 
putPropertiesToGrabBag(const Sequence<PropertyValue> & aProperties)1785 void Shape::putPropertiesToGrabBag( const Sequence< PropertyValue >& aProperties )
1786 {
1787     Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
1788     Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1789     const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
1790     if( mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName ) )
1791     {
1792         // get existing grab bag
1793         Sequence< PropertyValue > aGrabBag;
1794         xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
1795 
1796         std::vector<PropertyValue> aVec;
1797         aVec.reserve(aProperties.getLength());
1798 
1799         // put the new items
1800         std::transform(aProperties.begin(), aProperties.end(), std::back_inserter(aVec),
1801             [](const PropertyValue& rProp) {
1802                 PropertyValue aProp;
1803                 aProp.Name = rProp.Name;
1804                 aProp.Value = rProp.Value;
1805                 return aProp;
1806             });
1807 
1808         // put it back to the shape
1809         xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, aVec) ) );
1810     }
1811 }
1812 
getActualFillProperties(const Theme * pTheme,const FillProperties * pParentShapeFillProps) const1813 FillProperties Shape::getActualFillProperties(const Theme* pTheme, const FillProperties* pParentShapeFillProps) const
1814 {
1815     FillProperties aFillProperties;
1816     aFillProperties.moFillType = XML_noFill;
1817 
1818     // Reference shape properties
1819     aFillProperties.assignUsed( *mpShapeRefFillPropPtr );
1820 
1821     // Theme
1822     if( pTheme != nullptr )
1823     {
1824         if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) )
1825         {
1826             if( const FillProperties* pFillProps = pTheme->getFillStyle( pFillRef->mnThemedIdx ) )
1827                 aFillProperties.assignUsed( *pFillProps );
1828         }
1829     }
1830 
1831     // Properties specified directly for this shape
1832     aFillProperties.assignUsed(getFillProperties());
1833 
1834     // Parent shape's properties
1835     if ( pParentShapeFillProps != nullptr)
1836         if( getFillProperties().moFillType.has() && getFillProperties().moFillType.get() == XML_grpFill )
1837             aFillProperties.assignUsed( *pParentShapeFillProps );
1838 
1839     return aFillProperties;
1840 }
1841 
getActualLineProperties(const Theme * pTheme) const1842 LineProperties Shape::getActualLineProperties(const Theme* pTheme) const
1843 {
1844     LineProperties aLineProperties;
1845     aLineProperties.maLineFill.moFillType = XML_noFill;
1846 
1847     // Reference shape properties
1848     aLineProperties.assignUsed( *mpShapeRefLinePropPtr );
1849 
1850     // Theme
1851     if( pTheme != nullptr )
1852     {
1853         if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) )
1854         {
1855             if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) )
1856                 aLineProperties.assignUsed( *pLineProps );
1857         }
1858     }
1859 
1860     // Properties specified directly for this shape
1861     aLineProperties.assignUsed( getLineProperties() );
1862 
1863     return aLineProperties;
1864 }
1865 
getActualEffectProperties(const Theme * pTheme) const1866 EffectProperties Shape::getActualEffectProperties(const Theme* pTheme) const
1867 {
1868     EffectProperties aEffectProperties;
1869 
1870     // Reference shape properties
1871     aEffectProperties.assignUsed( *mpShapeRefEffectPropPtr );
1872 
1873     // Theme
1874     if( pTheme != nullptr )
1875     {
1876         if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) )
1877         {
1878             if( const EffectProperties* pEffectProps = pTheme->getEffectStyle( pEffectRef->mnThemedIdx ) )
1879                 aEffectProperties.assignUsed( *pEffectProps );
1880         }
1881     }
1882 
1883     // Properties specified directly for this shape
1884     aEffectProperties.assignUsed ( getEffectProperties() );
1885 
1886     return aEffectProperties;
1887 }
1888 
resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase & rFilter,const OUString & sFragment,const OUString & sType)1889 uno::Sequence< uno::Sequence< uno::Any > >  Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase& rFilter, const OUString& sFragment, const OUString& sType )
1890 {
1891     uno::Sequence< uno::Sequence< uno::Any > > xRelListTemp;
1892     sal_Int32 counter = 0;
1893 
1894     core::RelationsRef xRels = rFilter.importRelations( sFragment );
1895     if ( xRels )
1896     {
1897         core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc( sType );
1898         if ( xImageRels )
1899         {
1900             xRelListTemp.realloc( xImageRels->size() );
1901             for (auto const& imageRel : *xImageRels)
1902             {
1903                 uno::Sequence< uno::Any > diagramRelTuple (3);
1904                 // [0] => RID, [1] => InputStream [2] => extension
1905                 OUString sRelId = imageRel.second.maId;
1906 
1907                 diagramRelTuple[0] <<= sRelId;
1908                 OUString sTarget = xImageRels->getFragmentPathFromRelId( sRelId );
1909 
1910                 uno::Reference< io::XInputStream > xImageInputStrm( rFilter.openInputStream( sTarget ), uno::UNO_SET_THROW );
1911                 StreamDataSequence dataSeq;
1912                 if ( rFilter.importBinaryData( dataSeq, sTarget ) )
1913                 {
1914                     diagramRelTuple[1] <<= dataSeq;
1915                 }
1916 
1917                 diagramRelTuple[2] <<= sTarget.copy( sTarget.lastIndexOf(".") );
1918 
1919                 xRelListTemp[counter] = diagramRelTuple;
1920                 ++counter;
1921             }
1922             xRelListTemp.realloc(counter);
1923 
1924         }
1925     }
1926     return xRelListTemp;
1927 }
1928 
cloneFillProperties()1929 void Shape::cloneFillProperties()
1930 {
1931     auto pFillProperties = std::make_shared<FillProperties>();
1932     pFillProperties->assignUsed(*mpFillPropertiesPtr);
1933     mpFillPropertiesPtr = pFillProperties;
1934 }
1935 } }
1936 
1937 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1938