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