1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_wasm_strip.h>
22 #include <oox/drawingml/shape.hxx>
23 #include <drawingml/customshapeproperties.hxx>
24 #include <oox/drawingml/theme.hxx>
25 #include <drawingml/fillproperties.hxx>
26 #include <drawingml/fontworkhelpers.hxx>
27 #include <drawingml/graphicproperties.hxx>
28 #include <drawingml/lineproperties.hxx>
29 #include <drawingml/presetgeometrynames.hxx>
30 #include <drawingml/shape3dproperties.hxx>
31 #include <drawingml/scene3dhelper.hxx>
32 #include <oox/drawingml/effectproperties.hxx>
33 #include <oox/drawingml/shapepropertymap.hxx>
34 #include <drawingml/textbody.hxx>
35 #include <drawingml/textparagraph.hxx>
36 #include <drawingml/ThemeOverrideFragmentHandler.hxx>
37 #include <drawingml/table/tableproperties.hxx>
38 #include <oox/drawingml/chart/chartconverter.hxx>
39 #include <drawingml/chart/chartspacefragment.hxx>
40 #include <drawingml/chart/chartspacemodel.hxx>
41 #include <o3tl/safeint.hxx>
42 #include <o3tl/unit_conversion.hxx>
43 #include <oox/ppt/pptimport.hxx>
44 #include <oox/vml/vmldrawing.hxx>
45 #include <oox/vml/vmlshape.hxx>
46 #include <oox/vml/vmlshapecontainer.hxx>
47 #include <oox/core/xmlfilterbase.hxx>
48 #include <oox/helper/graphichelper.hxx>
49 #include <oox/helper/propertyset.hxx>
50 #include <oox/helper/modelobjecthelper.hxx>
51 #include <oox/mathml/imexport.hxx>
52 #include <oox/mathml/importutils.hxx>
53 #include <oox/token/properties.hxx>
54 #include "diagram/datamodel.hxx"
55 #include "diagram/diagramhelper.hxx"
57 #include <comphelper/classids.hxx>
58 #include <comphelper/propertysequence.hxx>
59 #include <comphelper/propertyvalue.hxx>
60 #include <comphelper/sequence.hxx>
61 #include <comphelper/diagnose_ex.hxx>
62 #include <tools/gen.hxx>
63 #include <tools/globname.hxx>
64 #include <tools/mapunit.hxx>
65 #include <editeng/unoprnms.hxx>
66 #include <com/sun/star/awt/FontSlant.hpp>
67 #include <com/sun/star/awt/Size.hpp>
68 #include <com/sun/star/awt/XBitmap.hpp>
69 #include <com/sun/star/awt/FontWeight.hpp>
70 #include <com/sun/star/graphic/XGraphic.hpp>
71 #include <com/sun/star/container/XNamed.hpp>
72 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
73 #include <com/sun/star/xml/dom/XDocument.hpp>
74 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
75 #include <com/sun/star/drawing/FillStyle.hpp>
76 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
77 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
78 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
79 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
80 #include <com/sun/star/drawing/XShapes.hpp>
81 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
82 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
83 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
84 #include <com/sun/star/drawing/ConnectorType.hpp>
85 #include <com/sun/star/embed/XEmbeddedObject.hpp>
86 #include <com/sun/star/text/XText.hpp>
87 #include <com/sun/star/table/BorderLine2.hpp>
88 #include <com/sun/star/table/ShadowFormat.hpp>
89 #include <com/sun/star/chart2/XChartDocument.hpp>
90 #include <com/sun/star/style/ParagraphAdjust.hpp>
91 #include <com/sun/star/io/XOutputStream.hpp>
92 #include <com/sun/star/lang/Locale.hpp>
93 #include <com/sun/star/i18n/ScriptType.hpp>
94 #include <com/sun/star/text/WritingMode2.hpp>
96 #include <basegfx/point/b2dpoint.hxx>
97 #include <basegfx/polygon/b2dpolygon.hxx>
98 #include <basegfx/matrix/b2dhommatrix.hxx>
99 #include <com/sun/star/document/XActionLockable.hpp>
100 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
101 #include <officecfg/Office/Common.hxx>
102 #include <svx/svdobj.hxx>
103 #include <svx/svdotable.hxx>
104 #include <svx/svdtrans.hxx>
105 #include <tools/stream.hxx>
106 #include <unotools/streamwrap.hxx>
107 #include <unotools/mediadescriptor.hxx>
108 #include <vcl/graph.hxx>
109 #include <vcl/graphicfilter.hxx>
110 #include <vcl/svapp.hxx>
111 #include <vcl/wmfexternal.hxx>
112 #include <sal/log.hxx>
113 #include <svx/sdtaitm.hxx>
114 #include <oox/drawingml/diagram/diagram.hxx>
115 #include <docmodel/theme/Theme.hxx>
116 #include <i18nlangtag/languagetag.hxx>
117 #include <i18nlangtag/mslangid.hxx>
119 using namespace ::oox::core
;
120 using namespace ::com::sun::star
;
121 using namespace ::com::sun::star::uno
;
122 using namespace ::com::sun::star::beans
;
123 using namespace ::com::sun::star::frame
;
124 using namespace ::com::sun::star::text
;
125 using namespace ::com::sun::star::drawing
;
126 using namespace ::com::sun::star::style
;
128 namespace oox::drawingml
{
131 : mpLinePropertiesPtr( std::make_shared
<LineProperties
>() )
132 , mpShapeRefLinePropPtr( std::make_shared
<LineProperties
>() )
133 , mpFillPropertiesPtr( std::make_shared
<FillProperties
>() )
134 , mpShapeRefFillPropPtr( std::make_shared
<FillProperties
>() )
135 , mpGraphicPropertiesPtr( std::make_shared
<GraphicProperties
>() )
136 , mpCustomShapePropertiesPtr( std::make_shared
<CustomShapeProperties
>() )
137 , mp3DPropertiesPtr( std::make_shared
<Shape3DProperties
>() )
138 , mpEffectPropertiesPtr( std::make_shared
<EffectProperties
>() )
139 , mpShapeRefEffectPropPtr( std::make_shared
<EffectProperties
>() )
140 , mpMasterTextListStyle( std::make_shared
<TextListStyle
>() )
142 , meFrameType( FRAMETYPE_GENERIC
)
144 , mnDiagramRotation( 0 )
148 , mbHiddenMasterShape( false )
151 , mbLockedCanvas( false )
152 , mbWordprocessingCanvas(false)
155 , mbHasLinkedTxbx( false )
157 , mpDiagramHelper( nullptr )
159 setDefaults(/*bDefaultHeight*/true);
163 Shape::Shape( const OUString
& rServiceName
, bool bDefaultHeight
)
164 : mpLinePropertiesPtr( std::make_shared
<LineProperties
>() )
165 , mpShapeRefLinePropPtr( std::make_shared
<LineProperties
>() )
166 , mpFillPropertiesPtr( std::make_shared
<FillProperties
>() )
167 , mpShapeRefFillPropPtr( std::make_shared
<FillProperties
>() )
168 , mpGraphicPropertiesPtr( std::make_shared
<GraphicProperties
>() )
169 , mpCustomShapePropertiesPtr( std::make_shared
<CustomShapeProperties
>() )
170 , mp3DPropertiesPtr( std::make_shared
<Shape3DProperties
>() )
171 , mpEffectPropertiesPtr( std::make_shared
<EffectProperties
>() )
172 , mpShapeRefEffectPropPtr( std::make_shared
<EffectProperties
>() )
173 , mpMasterTextListStyle( std::make_shared
<TextListStyle
>() )
175 , meFrameType( FRAMETYPE_GENERIC
)
177 , mnDiagramRotation( 0 )
181 , mbHiddenMasterShape( false )
184 , mbLockedCanvas( false )
185 , mbWordprocessingCanvas(false)
188 , mbHasLinkedTxbx( false )
190 , mpDiagramHelper( nullptr )
192 msServiceName
= rServiceName
;
193 setDefaults(bDefaultHeight
);
196 Shape::Shape( const ShapePtr
& pSourceShape
)
197 : mpTextBody(pSourceShape
->mpTextBody
)
198 , mpLinePropertiesPtr( pSourceShape
->mpLinePropertiesPtr
)
199 , mpShapeRefLinePropPtr( pSourceShape
->mpShapeRefLinePropPtr
)
200 , mpFillPropertiesPtr( pSourceShape
->mpFillPropertiesPtr
)
201 , mpShapeRefFillPropPtr( pSourceShape
->mpShapeRefFillPropPtr
)
202 , mpGraphicPropertiesPtr( pSourceShape
->mpGraphicPropertiesPtr
)
203 , mpCustomShapePropertiesPtr( pSourceShape
->mpCustomShapePropertiesPtr
)
204 , mpTablePropertiesPtr( pSourceShape
->mpTablePropertiesPtr
)
205 , mp3DPropertiesPtr( pSourceShape
->mp3DPropertiesPtr
)
206 , mpEffectPropertiesPtr (pSourceShape
->mpEffectPropertiesPtr
)
207 , mpShapeRefEffectPropPtr(pSourceShape
->mpShapeRefEffectPropPtr
)
208 , maShapeProperties( pSourceShape
->maShapeProperties
)
209 , mpMasterTextListStyle( pSourceShape
->mpMasterTextListStyle
)
210 , msServiceName( pSourceShape
->msServiceName
)
211 , msName( pSourceShape
->msName
)
212 , msInternalName( pSourceShape
->msInternalName
)
213 , msId( pSourceShape
->msId
)
214 , mnSubType( pSourceShape
->mnSubType
)
215 , moSubTypeIndex( pSourceShape
->moSubTypeIndex
)
216 , maShapeStyleRefs( pSourceShape
->maShapeStyleRefs
)
217 , maSize( pSourceShape
->maSize
)
218 , maPosition( pSourceShape
->maPosition
)
219 , meFrameType( pSourceShape
->meFrameType
)
220 , mnRotation( pSourceShape
->mnRotation
)
221 , mnDiagramRotation( pSourceShape
->mnDiagramRotation
)
222 , mbFlipH( pSourceShape
->mbFlipH
)
223 , mbFlipV( pSourceShape
->mbFlipV
)
224 , mbHidden( pSourceShape
->mbHidden
)
225 , mbHiddenMasterShape( pSourceShape
->mbHiddenMasterShape
)
226 , mbLocked( pSourceShape
->mbLocked
)
227 , mbWPGChild( pSourceShape
->mbWPGChild
)
228 , mbLockedCanvas( pSourceShape
->mbLockedCanvas
)
229 , mbWordprocessingCanvas(pSourceShape
->mbWordprocessingCanvas
)
230 , mbWps( pSourceShape
->mbWps
)
231 , mbTextBox( pSourceShape
->mbTextBox
)
232 , mbHasLinkedTxbx(false)
233 , maDiagramDoms( pSourceShape
->maDiagramDoms
)
234 , mnZOrder(pSourceShape
->mnZOrder
)
235 , mnZOrderOff(pSourceShape
->mnZOrderOff
)
236 , mnDataNodeType(pSourceShape
->mnDataNodeType
)
237 , mfAspectRatio(pSourceShape
->mfAspectRatio
)
238 , mpDiagramHelper( nullptr )
239 , msDiagramDataModelID(pSourceShape
->msDiagramDataModelID
)
244 // DiagramHelper should not be set here anymore, see
245 // propagateDiagramHelper below (maybe assert..?)
246 delete mpDiagramHelper
;
249 void Shape::prepareDiagramHelper(
250 const std::shared_ptr
< Diagram
>& rDiagramPtr
,
251 const std::shared_ptr
<::oox::drawingml::Theme
>& rTheme
,
254 // Prepare Diagram data collecting for this Shape
255 if( nullptr == mpDiagramHelper
&& FRAMETYPE_DIAGRAM
== meFrameType
)
257 mpDiagramHelper
= new AdvancedDiagramHelper(
265 void Shape::propagateDiagramHelper()
267 // Propagate collected Diagram data to data holder
268 if (FRAMETYPE_DIAGRAM
== meFrameType
&& nullptr != mpDiagramHelper
)
270 SdrObjGroup
* pAnchorObj
= dynamic_cast<SdrObjGroup
*>(SdrObject::getSdrObjectFromXShape(mxShape
));
274 mpDiagramHelper
->doAnchor(*pAnchorObj
, *this);
275 mpDiagramHelper
= nullptr;
279 // If propagation failed, delete/cleanup here. Since the DiagramHelper
280 // holds a Diagram and that this Shape it is necessary - the destructor
281 // will not be called and will be too late
282 if (nullptr != mpDiagramHelper
)
284 delete mpDiagramHelper
;
285 mpDiagramHelper
= nullptr;
289 void Shape::migrateDiagramHelperToNewShape(const ShapePtr
& pTarget
)
298 // no migrate target, but cleanup helper
299 delete mpDiagramHelper
;
300 mpDiagramHelper
= nullptr;
304 if(pTarget
->mpDiagramHelper
)
306 // this should no happen, but if there is already a helper, clean it up
307 delete pTarget
->mpDiagramHelper
;
308 pTarget
->mpDiagramHelper
= nullptr;
311 // exchange and reset to nullptr
312 pTarget
->mpDiagramHelper
= mpDiagramHelper
;
313 mpDiagramHelper
= nullptr;
316 table::TablePropertiesPtr
const & Shape::getTableProperties()
318 if ( !mpTablePropertiesPtr
)
319 mpTablePropertiesPtr
= std::make_shared
<table::TableProperties
>();
320 return mpTablePropertiesPtr
;
323 void Shape::setDefaults(bool bHeight
)
325 maDefaultShapeProperties
.setProperty(PROP_TextAutoGrowHeight
, false);
326 maDefaultShapeProperties
.setProperty(PROP_TextWordWrap
, true);
327 maDefaultShapeProperties
.setProperty(PROP_TextLeftDistance
, static_cast< sal_Int32
>( 250 ));
328 maDefaultShapeProperties
.setProperty(PROP_TextUpperDistance
, static_cast< sal_Int32
>( 125 ));
329 maDefaultShapeProperties
.setProperty(PROP_TextRightDistance
, static_cast< sal_Int32
>( 250 ));
330 maDefaultShapeProperties
.setProperty(PROP_TextLowerDistance
, static_cast< sal_Int32
>( 125 ));
332 maDefaultShapeProperties
.setProperty(PROP_CharHeight
, static_cast< float >( 18.0 ));
333 maDefaultShapeProperties
.setProperty(PROP_TextVerticalAdjust
, TextVerticalAdjust_TOP
);
334 maDefaultShapeProperties
.setProperty(PROP_ParaAdjust
,
335 static_cast<sal_Int16
>(ParagraphAdjust_LEFT
));
338 ::oox::vml::OleObjectInfo
& Shape::setOleObjectType()
340 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setOleObjectType - multiple frame types" );
341 meFrameType
= FRAMETYPE_OLEOBJECT
;
342 mxOleObjectInfo
= std::make_shared
<::oox::vml::OleObjectInfo
>( true );
343 return *mxOleObjectInfo
;
346 ChartShapeInfo
& Shape::setChartType( bool bEmbedShapes
)
348 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setChartType - multiple frame types" );
349 meFrameType
= FRAMETYPE_CHART
;
351 msServiceName
= u
"com.sun.star.drawing.temporaryForXMLImportOLE2Shape"_ustr
;
353 msServiceName
= u
"com.sun.star.drawing.OLE2Shape"_ustr
;
354 mxChartShapeInfo
= std::make_shared
<ChartShapeInfo
>( bEmbedShapes
);
355 return *mxChartShapeInfo
;
358 void Shape::setDiagramType()
360 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setDiagramType - multiple frame types" );
361 meFrameType
= FRAMETYPE_DIAGRAM
;
362 msServiceName
= u
"com.sun.star.drawing.GroupShape"_ustr
;
366 void Shape::setTableType()
368 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setTableType - multiple frame types" );
369 meFrameType
= FRAMETYPE_TABLE
;
370 msServiceName
= u
"com.sun.star.drawing.TableShape"_ustr
;
374 const ShapeStyleRef
* Shape::getShapeStyleRef( sal_Int32 nRefType
) const
376 ShapeStyleRefMap::const_iterator aIt
= maShapeStyleRefs
.find( nRefType
);
377 return (aIt
== maShapeStyleRefs
.end()) ? nullptr : &aIt
->second
;
380 void Shape::addShape(
381 ::oox::core::XmlFilterBase
& rFilterBase
,
383 const Reference
< XShapes
>& rxShapes
,
384 const basegfx::B2DHomMatrix
& aTransformation
,
385 const FillProperties
& rShapeOrParentShapeFillProps
,
386 ShapeIdMap
* pShapeMap
,
387 const oox::drawingml::ShapePtr
& pParentGroupShape
)
389 SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId
<< "'");
393 OUString
sServiceName( msServiceName
);
394 if( !sServiceName
.isEmpty() )
396 basegfx::B2DHomMatrix
aMatrix( aTransformation
);
397 Reference
< XShape
> xShape( createAndInsert( rFilterBase
, sServiceName
, pTheme
, rxShapes
, false, false, aMatrix
, rShapeOrParentShapeFillProps
, pParentGroupShape
) );
399 if( pShapeMap
&& !msId
.isEmpty() )
401 (*pShapeMap
)[ msId
] = shared_from_this();
404 // if this is a group shape, we have to add also each child shape
405 Reference
< XShapes
> xShapes( xShape
, UNO_QUERY
);
407 addChildren( rFilterBase
, *this, pTheme
, xShapes
, pShapeMap
, aMatrix
);
409 if (mbWordprocessingCanvas
&& !mbWPGChild
)
411 // This is a drawing canvas. In case the canvas has no fill and no stroke, Word does
412 // not render shadow or glow, even if it is set for the canvas. Thus we disable shadow
413 // and glow in this case for the ersatz background shape of the drawing canvas.
416 oox::drawingml::ShapePtr pBgShape
= getChildren().front();
417 const Reference
<css::drawing::XShape
>& xBgShape
= pBgShape
->getXShape();
418 Reference
<XPropertySet
> xBgProps(xBgShape
, uno::UNO_QUERY
);
419 drawing::FillStyle eFillStyle
= drawing::FillStyle_NONE
;
420 xBgProps
->getPropertyValue(u
"FillStyle"_ustr
) >>= eFillStyle
;
421 drawing::LineStyle eLineStyle
= drawing::LineStyle_NONE
;
422 xBgProps
->getPropertyValue(u
"LineStyle"_ustr
) >>= eLineStyle
;
423 if (eFillStyle
== drawing::FillStyle_NONE
424 && eLineStyle
== drawing::LineStyle_NONE
)
426 xBgProps
->setPropertyValue(UNO_NAME_SHADOW
, uno::Any(false));
427 xBgProps
->setPropertyValue(u
"GlowEffectRadius"_ustr
, uno::Any(sal_Int32(0)));
430 catch (const Exception
&)
432 TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::addShape mbWordprocessingCanvas");
436 if (isWPGChild() && xShape
)
438 // This is a wps shape and it is the child of the WPG, now copy the
439 // the text body properties to the xshape.
440 Reference
<XPropertySet
> xChildWPSProperties(xShape
, uno::UNO_QUERY
);
442 if (getTextBody() && xChildWPSProperties
)
444 xChildWPSProperties
->setPropertyValue(
445 UNO_NAME_TEXT_VERTADJUST
,
446 uno::Any(getTextBody()->getTextProperties().meVA
));
448 xChildWPSProperties
->setPropertyValue(
449 UNO_NAME_TEXT_LEFTDIST
,
450 uno::Any(getTextBody()->getTextProperties().moInsets
[0].has_value()
451 ? *getTextBody()->getTextProperties().moInsets
[0]
453 xChildWPSProperties
->setPropertyValue(
454 UNO_NAME_TEXT_UPPERDIST
,
455 uno::Any(getTextBody()->getTextProperties().moInsets
[1].has_value()
456 ? *getTextBody()->getTextProperties().moInsets
[1]
458 xChildWPSProperties
->setPropertyValue(
459 UNO_NAME_TEXT_RIGHTDIST
,
460 uno::Any(getTextBody()->getTextProperties().moInsets
[2].has_value()
461 ? *getTextBody()->getTextProperties().moInsets
[2]
463 xChildWPSProperties
->setPropertyValue(
464 UNO_NAME_TEXT_LOWERDIST
,
465 uno::Any(getTextBody()->getTextProperties().moInsets
[3].has_value()
466 ? *getTextBody()->getTextProperties().moInsets
[3]
470 // tdf#145147 Set the Hyperlink property to the child wps shape.
471 if (getShapeProperties().hasProperty(PROP_URL
)) try
473 uno::Any aAny
= getShapeProperties().getProperty(PROP_URL
);
474 OUString sUrl
= aAny
.get
<OUString
>();
476 xChildWPSProperties
->setPropertyValue(UNO_NAME_HYPERLINK
, aAny
);
478 catch (const Exception
&)
483 if( meFrameType
== FRAMETYPE_DIAGRAM
)
485 keepDiagramCompatibilityInfo();
487 // set DiagramHelper at SdrObjGroup
488 propagateDiagramHelper();
490 // Check if this is the PPTX import, so far converting SmartArt to a non-editable
491 // metafile is only implemented for DOCX.
492 bool bPowerPoint
= dynamic_cast<oox::ppt::PowerPointImport
*>(&rFilterBase
) != nullptr;
494 if (!officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get() && !bPowerPoint
)
495 convertSmartArtToMetafile( rFilterBase
);
498 NamedShapePairs
* pNamedShapePairs
= rFilterBase
.getDiagramFontHeights();
499 if (xShape
.is() && pNamedShapePairs
)
501 auto itPairs
= pNamedShapePairs
->find(getInternalName());
502 if (itPairs
!= pNamedShapePairs
->end())
504 auto it
= itPairs
->second
.find(shared_from_this());
505 if (it
!= itPairs
->second
.end())
507 // Our drawingml::Shape is in the list of an internal name, remember the now
509 it
->second
= std::move(xShape
);
515 catch( const Exception
& )
517 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" );
521 void Shape::setLockedCanvas(bool bLockedCanvas
)
523 mbLockedCanvas
= bLockedCanvas
;
526 void Shape::setWordprocessingCanvas(bool bWordprocessingCanvas
)
528 mbWordprocessingCanvas
= bWordprocessingCanvas
;
531 void Shape::setWPGChild(bool bWPG
)
536 void Shape::setWps(bool bWps
)
541 void Shape::setTextBox(bool bTextBox
)
543 mbTextBox
= bTextBox
;
546 void Shape::applyShapeReference( const Shape
& rReferencedShape
, bool bUseText
)
548 SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape
.msId
<< "' to '" << msId
<< "'");
550 if ( rReferencedShape
.mpTextBody
&& bUseText
)
551 mpTextBody
= std::make_shared
<TextBody
>( *rReferencedShape
.mpTextBody
);
554 maShapeProperties
= rReferencedShape
.maShapeProperties
;
555 mpShapeRefLinePropPtr
= std::make_shared
<LineProperties
>( rReferencedShape
.getActualLineProperties(nullptr) );
556 mpShapeRefFillPropPtr
= std::make_shared
<FillProperties
>( rReferencedShape
.getActualFillProperties(nullptr, nullptr) );
557 mpCustomShapePropertiesPtr
= std::make_shared
<CustomShapeProperties
>( *rReferencedShape
.mpCustomShapePropertiesPtr
);
558 mpTablePropertiesPtr
= rReferencedShape
.mpTablePropertiesPtr
? std::make_shared
<table::TableProperties
>( *rReferencedShape
.mpTablePropertiesPtr
) : nullptr;
559 mpShapeRefEffectPropPtr
= std::make_shared
<EffectProperties
>( rReferencedShape
.getActualEffectProperties(nullptr) );
560 mpMasterTextListStyle
= std::make_shared
<TextListStyle
>( *rReferencedShape
.mpMasterTextListStyle
);
561 maSize
= rReferencedShape
.maSize
;
562 maPosition
= rReferencedShape
.maPosition
;
563 mnRotation
= rReferencedShape
.mnRotation
;
564 mbFlipH
= rReferencedShape
.mbFlipH
;
565 mbFlipV
= rReferencedShape
.mbFlipV
;
566 mbHidden
= rReferencedShape
.mbHidden
;
567 mbLocked
= rReferencedShape
.mbLocked
;
572 struct ActionLockGuard
574 explicit ActionLockGuard(Reference
<drawing::XShape
> const& xShape
)
575 : m_xLockable(xShape
, UNO_QUERY
)
577 if (m_xLockable
.is()) {
578 m_xLockable
->addActionLock();
583 if (m_xLockable
.is()) {
584 m_xLockable
->removeActionLock();
588 Reference
<document::XActionLockable
> m_xLockable
;
593 // for group shapes, the following method is also adding each child
594 void Shape::addChildren(
595 XmlFilterBase
& rFilterBase
,
598 const Reference
< XShapes
>& rxShapes
,
599 ShapeIdMap
* pShapeMap
,
600 const basegfx::B2DHomMatrix
& aTransformation
)
602 for (auto const& child
: rMaster
.maChildren
)
604 child
->setMasterTextListStyle( mpMasterTextListStyle
);
605 child
->addShape( rFilterBase
, pTheme
, rxShapes
, aTransformation
, getFillProperties(), pShapeMap
, rMaster
.shared_from_this());
609 static SdrTextHorzAdjust
lcl_convertAdjust( ParagraphAdjust eAdjust
)
611 if (eAdjust
== ParagraphAdjust_LEFT
)
612 return SDRTEXTHORZADJUST_LEFT
;
613 else if (eAdjust
== ParagraphAdjust_RIGHT
)
614 return SDRTEXTHORZADJUST_RIGHT
;
615 else if (eAdjust
== ParagraphAdjust_CENTER
)
616 return SDRTEXTHORZADJUST_CENTER
;
617 return SDRTEXTHORZADJUST_LEFT
;
620 static TextHorizontalAdjust
lcl_convertTextAdjust(ParagraphAdjust eAdjust
)
622 if (eAdjust
== ParagraphAdjust_LEFT
)
623 return drawing::TextHorizontalAdjust_LEFT
;
624 else if (eAdjust
== ParagraphAdjust_RIGHT
)
625 return drawing::TextHorizontalAdjust_RIGHT
;
627 return drawing::TextHorizontalAdjust_BLOCK
;
630 // LO does not interpret properties in styles belonging to the text content of a FontWork shape,
631 // but only those in the shape style. This method copies properties from the text content styles to
633 static void lcl_copyCharPropsToShape(const uno::Reference
<drawing::XShape
>& xShape
,
634 const TextBodyPtr
& pTextBody
,
635 const ::oox::core::XmlFilterBase
& rFilter
)
637 if (!xShape
.is() || !pTextBody
)
640 Reference
<XPropertySet
> xSet(xShape
, UNO_QUERY
);
644 // Content stretches or scales to given width and height, thus disable autogrow.
645 xSet
->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT
, uno::Any(false));
646 xSet
->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH
, uno::Any(false));
648 // LibreOffice is not able (as of Nov 2022) to use different styles for the paragraphs or
649 // characters in FontWork, since that was not allowed in old binary WordArt. We use the
650 // properties of the first non empty paragraph for now.
651 const TextParagraphVector
& rParagraphs
= pTextBody
->getParagraphs();
652 auto aParaIt
= std::find_if_not(rParagraphs
.cbegin(), rParagraphs
.cend(),
653 [](const std::shared_ptr
<TextParagraph
> pParagraph
) {
654 return pParagraph
->getRuns().empty();
656 if (aParaIt
!= rParagraphs
.cend())
658 const std::shared_ptr
<TextParagraph
>& pParagraph
= *aParaIt
;
659 const TextRunVector
& rRuns
= pParagraph
->getRuns();
660 auto aRunIt
= std::find_if_not(rRuns
.cbegin(), rRuns
.cend(),
661 [](const std::shared_ptr
<TextRun
> pRun
)
663 return pRun
->getText().isEmpty()
664 || pRun
->getText() == " "
665 || pRun
->getText().toChar() == 0xA0; // NBSP
667 if (aRunIt
!= rRuns
.cend())
669 const std::shared_ptr
<TextRun
>& pRun
= *aRunIt
;
670 TextCharacterProperties
& rCharProps
= pRun
->getTextCharacterProperties();
673 if (rCharProps
.moLang
.has_value() && !rCharProps
.moLang
.value().isEmpty())
675 LanguageTag
aTag(rCharProps
.moLang
.value());
676 const css::lang::Locale
& aLocale(aTag
.getLocale(false));
677 switch (MsLangId::getScriptType(aTag
.getLanguageType()))
679 case css::i18n::ScriptType::LATIN
:
680 xSet
->setPropertyValue(u
"CharLocale"_ustr
, uno::Any(aLocale
));
682 case css::i18n::ScriptType::ASIAN
:
683 xSet
->setPropertyValue(u
"CharLocaleAsian"_ustr
, uno::Any(aLocale
));
685 case css::i18n::ScriptType::COMPLEX
:
686 xSet
->setPropertyValue(u
"CharLocaleComplex"_ustr
, uno::Any(aLocale
));
692 // Font Weight, Posture, Height
693 if (rCharProps
.moBold
.has_value() && rCharProps
.moBold
.value())
695 xSet
->setPropertyValue(UNO_NAME_CHAR_WEIGHT
, uno::Any(css::awt::FontWeight::BOLD
));
697 if (rCharProps
.moItalic
.has_value() && rCharProps
.moItalic
.value())
699 xSet
->setPropertyValue(UNO_NAME_CHAR_POSTURE
,
700 uno::Any(css::awt::FontSlant::FontSlant_ITALIC
));
702 if (rCharProps
.moHeight
.has_value())
704 sal_Int32 nHeight
= rCharProps
.moHeight
.value() / 100;
705 xSet
->setPropertyValue(UNO_NAME_CHAR_HEIGHT
, uno::Any(nHeight
));
708 // Put theme fonts into shape properties
710 sal_Int16 nFontPitch
= 0;
711 sal_Int16 nFontFamily
= 0;
713 if (const Theme
* pTheme
= rFilter
.getCurrentTheme())
716 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-lt"))
718 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
721 xSet
->setPropertyValue(u
"CharFontName"_ustr
, uno::Any(sFontName
));
722 xSet
->setPropertyValue(u
"CharFontPitch"_ustr
, uno::Any(nFontPitch
));
723 xSet
->setPropertyValue(u
"CharFontFamily"_ustr
, uno::Any(nFontFamily
));
727 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-ea"))
729 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
732 xSet
->setPropertyValue(u
"CharFontNameAsian"_ustr
, uno::Any(sFontName
));
733 xSet
->setPropertyValue(u
"CharFontPitchAsian"_ustr
, uno::Any(nFontPitch
));
734 xSet
->setPropertyValue(u
"CharFontFamilyAsian"_ustr
, uno::Any(nFontFamily
));
738 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-cs"))
740 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
743 xSet
->setPropertyValue(u
"CharFontNameComplex"_ustr
, uno::Any(sFontName
));
744 xSet
->setPropertyValue(u
"CharFontPitchComplex"_ustr
, uno::Any(nFontPitch
));
745 xSet
->setPropertyValue(u
"CharFontFamilyComplex"_ustr
, uno::Any(nFontFamily
));
750 // Replace theme fonts with formatting at run if any. ToDo: Inspect paragraph too?
752 bRet
= rCharProps
.maLatinFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
754 // In case there is no direct font, try to look it up as a theme reference.
755 bRet
= rCharProps
.maLatinThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr,
760 xSet
->setPropertyValue(u
"CharFontName"_ustr
, uno::Any(sFontName
));
761 xSet
->setPropertyValue(u
"CharFontPitch"_ustr
, uno::Any(nFontPitch
));
762 xSet
->setPropertyValue(u
"CharFontFamily"_ustr
, uno::Any(nFontFamily
));
765 bRet
= rCharProps
.maAsianFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
767 // In case there is no direct font, try to look it up as a theme reference.
768 bRet
= rCharProps
.maAsianThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr,
772 xSet
->setPropertyValue(u
"CharFontNameAsian"_ustr
, uno::Any(sFontName
));
773 xSet
->setPropertyValue(u
"CharFontPitchAsian"_ustr
, uno::Any(nFontPitch
));
774 xSet
->setPropertyValue(u
"CharFontFamilyAsian"_ustr
, uno::Any(nFontFamily
));
778 = rCharProps
.maComplexFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
780 // In case there is no direct font, try to look it up as a theme reference.
781 bRet
= rCharProps
.maComplexThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, nullptr,
785 xSet
->setPropertyValue(u
"CharFontNameComplex"_ustr
, uno::Any(sFontName
));
786 xSet
->setPropertyValue(u
"CharFontPitchComplex"_ustr
, uno::Any(nFontPitch
));
787 xSet
->setPropertyValue(u
"CharFontFamilyComplex"_ustr
, uno::Any(nFontFamily
));
790 // LO uses shape properties, MS Office character properties. Copy them from char to shape.
792 if (rCharProps
.moTextOutlineProperties
.has_value())
794 oox::drawingml::ShapePropertyMap
aStrokeShapeProps(rFilter
.getModelObjectHelper());
795 rCharProps
.moTextOutlineProperties
.value().pushToPropMap(
796 aStrokeShapeProps
, rFilter
.getGraphicHelper());
797 for (const auto& rProp
: aStrokeShapeProps
.makePropertyValueSequence())
799 xSet
->setPropertyValue(rProp
.Name
, rProp
.Value
);
804 xSet
->setPropertyValue(UNO_NAME_LINESTYLE
, uno::Any(drawing::LineStyle_NONE
));
808 // ToDo: Replace flip and rotate constants in parameters with actual values.
809 // tdf#155327 If color is not explicitly set, MS Office uses scheme color 'tx1'.
810 oox::drawingml::ShapePropertyMap
aFillShapeProps(rFilter
.getModelObjectHelper());
811 if (!rCharProps
.maFillProperties
.moFillType
.has_value())
812 rCharProps
.maFillProperties
.moFillType
= XML_solidFill
;
813 if (!rCharProps
.maFillProperties
.maFillColor
.isUsed())
814 rCharProps
.maFillProperties
.maFillColor
.setSchemeClr(XML_tx1
);
815 rCharProps
.maFillProperties
.pushToPropMap(aFillShapeProps
, rFilter
.getGraphicHelper(),
816 /*nShapeRotation*/ 0,
817 /*nPhClr*/ API_RGB_TRANSPARENT
,
818 /*aShapeSize*/ css::awt::Size(0, 0),
820 /*bFlipH*/ false, /*bFlipV*/ false,
821 /*bIsCustomShape*/ true);
822 for (const auto& rProp
: aFillShapeProps
.makePropertyValueSequence())
824 xSet
->setPropertyValue(rProp
.Name
, rProp
.Value
);
827 // ToDo: Import WordArt glow and simple shadow effects. They are available in LO.
830 // LO does not evaluate paragraph alignment in text path mode. Use text area anchor instead.
832 ParagraphAdjust eAdjust
= ParagraphAdjust_LEFT
;
833 if (pParagraph
->getProperties().getParaAdjust())
834 eAdjust
= *pParagraph
->getProperties().getParaAdjust();
835 xSet
->setPropertyValue(u
"ParaAdjust"_ustr
, uno::Any(eAdjust
));
836 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(xShape
);
838 SdrTextHorzAdjust eHorzAdjust
= lcl_convertAdjust(eAdjust
);
839 pShape
->SetMergedItem(SdrTextHorzAdjustItem(eHorzAdjust
));
843 // Vertical adjustment is only meaningful for OOXML WordArt shapes of 'Follow Path' kinds. We set
844 // it so, that text position is approximately same as in MS Office.
845 const OUString sMSPresetType
= pTextBody
->getTextProperties().msPrst
;
846 const OUString sFontworkType
= PresetGeometryTypeNames::GetFontworkType(sMSPresetType
);
847 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(xShape
);
849 if (sFontworkType
== "fontwork-arch-up-curve" || sFontworkType
== "fontwork-circle-curve")
850 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM
));
851 else if (sFontworkType
== "fontwork-arch-down-curve")
852 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP
));
854 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_CENTER
));
857 // Some helper methods for createAndInsert
860 // mirrors aTransformation at its center axis
861 // only valid if neither rotation or shear included
862 void lcl_mirrorAtCenter(basegfx::B2DHomMatrix
& aTransformation
, bool bFlipH
, bool bFlipV
)
864 if (!bFlipH
&& !bFlipV
)
866 basegfx::B2DPoint
aCenter(0.5, 0.5);
867 aCenter
*= aTransformation
;
868 aTransformation
.translate(-aCenter
);
869 aTransformation
.scale(bFlipH
? -1.0 : 1.0, bFlipV
? -1.0 : 1.0);
870 aTransformation
.translate(aCenter
);
874 // only valid if neither rotation or shear included
875 void lcl_doSpecialMSOWidthHeightToggle(basegfx::B2DHomMatrix
& aTransformation
)
877 // The values are directly set at the matrix without any matrix multiplication.
878 // That way it is valid for lines too. Those have zero width or height.
879 const double fSx(aTransformation
.get(0, 0));
880 const double fSy(aTransformation
.get(1, 1));
881 const double fTx(aTransformation
.get(0, 2));
882 const double fTy(aTransformation
.get(1, 2));
883 aTransformation
.set(0, 0, fSy
);
884 aTransformation
.set(1, 1, fSx
);
885 aTransformation
.set(0, 2, fTx
+ 0.5 * (fSx
- fSy
));
886 aTransformation
.set(1, 2, fTy
+ 0.5 * (fSy
- fSx
));
890 void lcl_RotateAtCenter(basegfx::B2DHomMatrix
& aTransformation
, sal_Int32 nMSORotationAngle
)
892 if (nMSORotationAngle
== 0)
894 double fRad
= basegfx::deg2rad
<60000>(nMSORotationAngle
);
895 basegfx::B2DPoint
aCenter(0.5, 0.5);
896 aCenter
*= aTransformation
;
897 aTransformation
.translate(-aCenter
);
898 aTransformation
.rotate(fRad
);
899 aTransformation
.translate(aCenter
);
903 Degree100
lcl_MSORotateAngleToAPIAngle(const sal_Int32 nMSORotationAngle
)
905 // Converts a shape rotation angle from MSO to angle for API property RotateAngle
906 // from unit 1/60000 deg to unit 1/100 deg
907 Degree100
nAngle(nMSORotationAngle
/ 600);
908 // API RotateAngle has opposite direction than nMSORotationAngle, thus 'minus'.
909 return NormAngle36000(-nAngle
);
913 Reference
< XShape
> const & Shape::createAndInsert(
914 ::oox::core::XmlFilterBase
& rFilterBase
,
915 const OUString
& rServiceName
,
917 const css::uno::Reference
< css::drawing::XShapes
>& rxShapes
,
919 bool bDoNotInsertEmptyTextBody
,
920 basegfx::B2DHomMatrix
& aParentTransformation
,
921 const FillProperties
& rShapeOrParentShapeFillProps
,
922 const oox::drawingml::ShapePtr
& pParentGroupShape
)
924 bool bIsEmbMedia
= false;
925 SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId
<< "' service='" << rServiceName
<< "'");
927 formulaimport::XmlStreamBuilder
* pMathXml(nullptr);
930 for (auto const& it
: mpTextBody
->getParagraphs())
932 if (it
->HasMathXml())
934 if (!mpTextBody
->isEmpty() || pMathXml
!= nullptr)
936 SAL_WARN("oox.drawingml", "losing a Math object...");
940 pMathXml
= &it
->GetMathXml();
946 // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height
947 if ( mpTablePropertiesPtr
&& rServiceName
== "com.sun.star.drawing.TableShape" )
950 for (auto const& elem
: mpTablePropertiesPtr
->getTableGrid())
952 maSize
.Width
= o3tl::saturating_add(maSize
.Width
, static_cast<sal_Int32
>(elem
));
955 for (auto const& elem
: mpTablePropertiesPtr
->getTableRows())
957 // WARN: If some rows can't fit the content, this is not the final height
958 maSize
.Height
= o3tl::saturating_add(maSize
.Height
, elem
.getHeight());
962 awt::Rectangle
aShapeRectHmm(
963 o3tl::convert(maPosition
.X
, o3tl::Length::emu
, o3tl::Length::mm100
),
964 o3tl::convert(maPosition
.Y
, o3tl::Length::emu
, o3tl::Length::mm100
),
965 o3tl::convert(maSize
.Width
, o3tl::Length::emu
, o3tl::Length::mm100
),
966 o3tl::convert(maSize
.Height
, o3tl::Length::emu
, o3tl::Length::mm100
));
968 OUString aServiceName
;
971 // convert this shape to OLE
972 aServiceName
= u
"com.sun.star.drawing.OLE2Shape"_ustr
;
973 msServiceName
= aServiceName
;
974 meFrameType
= FRAMETYPE_GENERIC
; // not OLEOBJECT, no stream in package
977 else if (rServiceName
== "com.sun.star.drawing.GraphicObjectShape" &&
978 mpGraphicPropertiesPtr
&& !mpGraphicPropertiesPtr
->m_sMediaPackageURL
.isEmpty())
980 aServiceName
= finalizeServiceName( rFilterBase
, u
"com.sun.star.presentation.MediaShape"_ustr
, aShapeRectHmm
);
985 aServiceName
= finalizeServiceName( rFilterBase
, rServiceName
, aShapeRectHmm
);
987 // Use custom shape instead of GraphicObjectShape if the image is cropped to
988 // shape. Except rectangle, which does not require further cropping
989 bool bIsCroppedGraphic
= (aServiceName
== "com.sun.star.drawing.GraphicObjectShape" &&
990 !mpCustomShapePropertiesPtr
->representsDefaultShape());
992 bool bIsCustomShape
= (aServiceName
== "com.sun.star.drawing.CustomShape" || bIsCroppedGraphic
);
993 bool bIsConnectorShape
= (aServiceName
== "com.sun.star.drawing.ConnectorShape");
995 // Look for 3D. Its z-rotation and extrusion color become shape properties. We consider a
996 // z-rotation of an image even we currently do not extrude an image to 3D-scene.
997 bool bBlockExtrusion
= !bIsCustomShape
&& mp3DPropertiesPtr
->mnPreset
.has_value();
998 double fShapeRotateInclCamera
= 0.0; // unit rad; same orientation as shape property RotateAngle
999 Color aExtrusionColor
;
1000 Scene3DHelper aScene3DHelper
;
1001 bool bHas3DEffect
= aScene3DHelper
.setExtrusionProperties(
1002 mp3DPropertiesPtr
, mnRotation
, getCustomShapeProperties()->getExtrusionPropertyMap(),
1003 fShapeRotateInclCamera
, aExtrusionColor
, bBlockExtrusion
);
1004 // Currently the other places use unit 1/60000deg and MSO shape rotate orientation.
1005 sal_Int32 nShapeRotateInclCamera
= -basegfx::rad2deg
<60000>(fShapeRotateInclCamera
);
1006 bool bIs3DGraphic
= aServiceName
== "com.sun.star.drawing.GraphicObjectShape" && bHas3DEffect
;
1007 bIsCustomShape
|= bIs3DGraphic
;
1009 // The extrusion color does not belong to the extrusion properties but is secondary color in
1010 // the style of the shape, FillColor2 in API. The case that no extrusion color was set is handled
1011 // further down when FillProperties and LineProperties are handled.
1012 if (aExtrusionColor
.isUsed())
1014 // FillColor2 is not yet transformed to ComplexColor.
1015 ::Color aColor
= aExtrusionColor
.getColor(rFilterBase
.getGraphicHelper());
1016 maShapeProperties
.setProperty(PROP_FillColor2
, aColor
);
1021 aScene3DHelper
.setLightingProperties(mp3DPropertiesPtr
, fShapeRotateInclCamera
,
1022 getCustomShapeProperties()->getExtrusionPropertyMap());
1023 oox::Scene3DHelper::setMaterialProperties(
1024 mp3DPropertiesPtr
, getCustomShapeProperties()->getExtrusionPropertyMap());
1027 if (bIsCroppedGraphic
|| bIs3DGraphic
)
1029 aServiceName
= "com.sun.star.drawing.CustomShape";
1030 mpGraphicPropertiesPtr
->mbIsCustomShape
= true;
1031 mpGraphicPropertiesPtr
->mbIsExtruded
= bIs3DGraphic
;
1033 bool bUseRotationTransform
= ( !mbWps
||
1034 aServiceName
== "com.sun.star.drawing.LineShape" ||
1035 aServiceName
== "com.sun.star.drawing.GroupShape" ||
1039 basegfx::B2DHomMatrix aTransformation
; // will be cumulative transformation of this object
1041 // Special for SmartArt import. Rotate diagram's shape around object's center before sizing.
1042 if (bUseRotationTransform
&& mnDiagramRotation
!= 0)
1044 aTransformation
.translate(-0.5, -0.5);
1045 aTransformation
.rotate(basegfx::deg2rad
<60000>(mnDiagramRotation
));
1046 aTransformation
.translate(0.5, 0.5);
1049 bool bLineShape
= aServiceName
== "com.sun.star.drawing.LineShape";
1050 bool bTopWriterLine
= !pParentGroupShape
&& mbWps
&& bLineShape
;
1051 // Build object matrix from shape size and position; corresponds to MSO ext and off
1052 // Only LineShape and ConnectorShape may have zero width or height.
1053 if (bLineShape
|| aServiceName
== "com.sun.star.drawing.ConnectorShape")
1055 // For toplevel Writer lines, size is included in the point coordinates.
1056 if (!bTopWriterLine
)
1058 aTransformation
.scale(maSize
.Width
, maSize
.Height
);
1063 aTransformation
.scale(maSize
.Width
? maSize
.Width
: 1.0,
1064 maSize
.Height
? maSize
.Height
: 1.0);
1067 // Evaluate object flip. Other shapes than custom shapes have no attribute for flip but use
1068 // negative scale. Flip in MSO is at object center.
1069 if (!bIsCustomShape
&& (mbFlipH
|| mbFlipV
))
1070 lcl_mirrorAtCenter(aTransformation
, mbFlipH
, mbFlipV
);
1072 // Evaluate parent flip.
1073 // A CustomShape has mirror not as negative scale, but as attributes.
1074 basegfx::B2DVector
aParentScale(1.0, 1.0);
1075 basegfx::B2DVector
aParentTranslate(0.0, 0.0);
1076 double fParentRotate(0.0);
1077 double fParentShearX(0.0);
1078 if (pParentGroupShape
)
1080 aParentTransformation
.decompose(aParentScale
, aParentTranslate
, fParentRotate
, fParentShearX
);
1083 lcl_mirrorAtCenter(aTransformation
, aParentScale
.getX() < 0, aParentScale
.getY() < 0);
1084 if(aParentScale
.getX() < 0)
1086 if(aParentScale
.getY() < 0)
1091 if (maPosition
.X
!= 0 || maPosition
.Y
!= 0)
1093 // if global position is used, add it to transformation
1094 if (mbWps
&& pParentGroupShape
== nullptr)
1095 aTransformation
.translate(
1096 o3tl::convert(maPosition
.X
, o3tl::Length::mm100
, o3tl::Length::emu
),
1097 o3tl::convert(maPosition
.Y
, o3tl::Length::mm100
, o3tl::Length::emu
));
1099 aTransformation
.translate(maPosition
.X
, maPosition
.Y
);
1102 // Apply further parent transformations. First scale object then rotate. Other way round would
1103 // introduce shearing.
1105 // The attributes chExt and chOff of the group in oox file contain the values on which the size
1106 // and position of the child is based on. If they differ from the actual size of the group as
1107 // given in its ext and off attributes, the child has to be transformed according the new values.
1108 if (pParentGroupShape
)
1110 // ToDo: A diagram in a group might need special handling because it cannot flip and only
1111 // resize uniformly. But currently it is imported with zero size, see tdf#139575. That needs
1112 // to be fixed beforehand.
1114 // Scaling is done from left/top edges of the group. So these need to become coordinate axes.
1115 aTransformation
.translate(-pParentGroupShape
->maChPosition
.X
,
1116 -pParentGroupShape
->maChPosition
.Y
);
1118 // oox allows zero or missing attribute chExt. In that case the scaling factor is 1.
1119 // Transform2DContext::onCreateContext has set maChSize to maSize for groups in oox file in
1120 // such cases. For own made groups (e.g. diagrams) that is missing.
1121 // The factors cumulate on the way through the parent groups, so we do not use maSize of the
1122 // direct parent group but the cumulated value from aParentScale.
1123 double fFactorX
= 1.0;
1124 double fFactorY
= 1.0;
1125 if (pParentGroupShape
->maChSize
.Width
!= 0)
1126 fFactorX
= aParentScale
.getX() / pParentGroupShape
->maChSize
.Width
;
1127 if (pParentGroupShape
->maChSize
.Height
!= 0)
1128 fFactorY
= aParentScale
.getY() / pParentGroupShape
->maChSize
.Height
;
1129 if (fFactorX
!= 1 || fFactorY
!= 1)
1131 // It depends on the object rotation angle whether scaling is applied to switched
1132 // width and height. MSO acts strange in that case (as of May 2021).
1133 const sal_Int32
nDeg(mnRotation
/ 60000);
1134 const bool bNeedsMSOWidthHeightToggle
1135 = (nDeg
>= 45 && nDeg
< 135) || (nDeg
>= 225 && nDeg
< 315);
1136 if (bNeedsMSOWidthHeightToggle
)
1137 lcl_doSpecialMSOWidthHeightToggle(aTransformation
);
1139 aTransformation
.scale(fFactorX
, fFactorY
);
1141 if (bNeedsMSOWidthHeightToggle
)
1143 lcl_doSpecialMSOWidthHeightToggle(aTransformation
);
1144 // In case of flip the special case needs an additional 180deg rotation.
1145 if ((aParentScale
.getX() < 0) != (aParentScale
.getY() < 0))
1146 lcl_RotateAtCenter(aTransformation
, 10800000);
1151 // Apply object rotation at current object center
1152 // The flip contained in aParentScale will affect orientation of object rotation angle.
1153 sal_Int16 nOrientation
= ((aParentScale
.getX() < 0) != (aParentScale
.getY() < 0)) ? -1 : 1;
1154 // ToDo: Not sure about the restrictions given by bUseRotationTransform.
1155 if (bUseRotationTransform
&& nShapeRotateInclCamera
!= 0)
1157 lcl_RotateAtCenter(aTransformation
, nOrientation
* nShapeRotateInclCamera
);
1160 if (fParentRotate
!= 0.0)
1161 aTransformation
.rotate(fParentRotate
);
1162 if (!aParentTranslate
.equalZero())
1163 aTransformation
.translate(aParentTranslate
);
1165 aParentTransformation
= aTransformation
;
1167 constexpr double fEmuToMm100
= o3tl::convert(1.0, o3tl::Length::emu
, o3tl::Length::mm100
);
1168 if (!bTopWriterLine
)
1170 aTransformation
.scale(fEmuToMm100
, fEmuToMm100
);
1173 // OOXML flips shapes before rotating them, so the rotation needs to be inverted
1174 if( bIsCustomShape
&& mbFlipH
!= mbFlipV
)
1176 basegfx::B2DVector aScale
, aTranslate
;
1177 double fRotate
, fShearX
;
1178 aTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1182 basegfx::B2DPoint
aCenter(0.5, 0.5);
1183 aCenter
*= aTransformation
;
1184 aTransformation
.translate( -aCenter
.getX(), -aCenter
.getY() );
1185 aTransformation
.rotate( fRotate
* -2.0 );
1186 aTransformation
.translate( aCenter
.getX(), aCenter
.getY() );
1190 // special for lineshape
1193 ::basegfx::B2DPolygon aPoly
;
1194 aPoly
.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1197 // No transform of individual points, everything apart from size is part of the
1198 // transform matrix.
1199 sal_Int32 nMM100Width
= o3tl::convert(maSize
.Width
, o3tl::Length::emu
, o3tl::Length::mm100
);
1200 sal_Int32 nMM100Height
= o3tl::convert(maSize
.Height
, o3tl::Length::emu
, o3tl::Length::mm100
);
1201 aPoly
.insert(1, ::basegfx::B2DPoint(nMM100Width
, nMM100Height
));
1205 aPoly
.insert( 1, ::basegfx::B2DPoint( maSize
.Width
? 1 : 0, maSize
.Height
? 1 : 0 ) );
1206 aPoly
.transform( aTransformation
);
1209 // now creating the corresponding PolyPolygon
1210 sal_Int32 i
, nNumPoints
= aPoly
.count();
1211 uno::Sequence
< awt::Point
> aPointSequence( nNumPoints
);
1212 awt::Point
* pPoints
= aPointSequence
.getArray();
1213 for( i
= 0; i
< nNumPoints
; ++i
)
1215 basegfx::B2DPoint
aPoint( aPoly
.getB2DPoint( i
) );
1217 // Guard against zero width or height.
1220 const basegfx::B2DPoint
& rPreviousPoint
= aPoly
.getB2DPoint(i
- 1);
1221 if (aPoint
.getX() - rPreviousPoint
.getX() == 0)
1222 aPoint
.setX(aPoint
.getX() + 1);
1223 if (aPoint
.getY() - rPreviousPoint
.getY() == 0)
1224 aPoint
.setY(aPoint
.getY() + 1);
1227 pPoints
[i
] = awt::Point(static_cast<sal_Int32
>(aPoint
.getX()), static_cast<sal_Int32
>(aPoint
.getY()));
1229 uno::Sequence
< uno::Sequence
< awt::Point
> > aPolyPolySequence( 1 );
1230 aPolyPolySequence
.getArray()[ 0 ] = std::move(aPointSequence
);
1232 maShapeProperties
.setProperty(PROP_PolyPolygon
, aPolyPolySequence
);
1234 if ( aServiceName
== "com.sun.star.drawing.ConnectorShape" )
1236 ::basegfx::B2DPolygon aPoly
;
1237 aPoly
.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1238 aPoly
.insert( 1, ::basegfx::B2DPoint( maSize
.Width
? 1 : 0, maSize
.Height
? 1 : 0 ) );
1239 aPoly
.transform( aTransformation
);
1241 basegfx::B2DPoint
aStartPosition( aPoly
.getB2DPoint( 0 ) );
1242 basegfx::B2DPoint
aEndPosition( aPoly
.getB2DPoint( 1 ) );
1243 awt::Point
aAWTStartPosition( static_cast< sal_Int32
>( aStartPosition
.getX() ), static_cast< sal_Int32
>( aStartPosition
.getY() ) );
1244 awt::Point
aAWTEndPosition( static_cast< sal_Int32
>( aEndPosition
.getX() ), static_cast< sal_Int32
>( aEndPosition
.getY() ) );
1246 maShapeProperties
.setProperty(PROP_StartPosition
, aAWTStartPosition
);
1247 maShapeProperties
.setProperty(PROP_EndPosition
, aAWTEndPosition
);
1249 else if (!bLineShape
|| bTopWriterLine
)
1251 // now set transformation for this object
1252 HomogenMatrix3 aMatrix
;
1254 aMatrix
.Line1
.Column1
= aTransformation
.get(0,0);
1255 aMatrix
.Line1
.Column2
= aTransformation
.get(0,1);
1256 aMatrix
.Line1
.Column3
= aTransformation
.get(0,2);
1258 aMatrix
.Line2
.Column1
= aTransformation
.get(1,0);
1259 aMatrix
.Line2
.Column2
= aTransformation
.get(1,1);
1260 aMatrix
.Line2
.Column3
= aTransformation
.get(1,2);
1262 aMatrix
.Line3
.Column1
= 0;
1263 aMatrix
.Line3
.Column2
= 0;
1264 aMatrix
.Line3
.Column3
= 1;
1266 maShapeProperties
.setProperty(PROP_Transformation
, aMatrix
);
1269 Reference
< lang::XMultiServiceFactory
> xServiceFact( rFilterBase
.getModel(), UNO_QUERY_THROW
);
1270 if ( !mxShape
.is() )
1272 mxShape
.set( xServiceFact
->createInstance( aServiceName
), UNO_QUERY_THROW
);
1275 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
1278 if( !msName
.isEmpty() )
1280 Reference
< container::XNamed
> xNamed( mxShape
, UNO_QUERY
);
1282 xNamed
->setName( msName
);
1284 if( !msDescription
.isEmpty() )
1286 xSet
->setPropertyValue( u
"Description"_ustr
, Any( msDescription
) );
1290 xSet
->setPropertyValue(u
"Decorative"_ustr
, Any(m_isDecorative
));
1292 if (!msMacro
.isEmpty())
1294 putPropertyToGrabBag(u
"mso-sp-macro"_ustr
, Any(msMacro
));
1296 if (!msTextLink
.isEmpty())
1298 putPropertyToGrabBag(u
"mso-sp-textlink"_ustr
, Any(msTextLink
));
1300 if (!mbFLocksText
) // set only if "false", otherwise it will use "true" by default
1302 putPropertyToGrabBag(u
"mso-sp-fLocksText"_ustr
, Any(mbFLocksText
));
1306 putPropertyToGrabBag(u
"mso-sp-fPublished"_ustr
, Any(mbFPublished
));
1308 if (!msTitle
.isEmpty())
1310 xSet
->setPropertyValue(u
"Title"_ustr
, Any(msTitle
));
1313 // get tooltip attribute of <hlinkClick>
1315 getShapeProperties().getProperty(PROP_Representation
) >>= sTooltip
;
1316 if (!sTooltip
.isEmpty())
1317 putPropertyToGrabBag(u
"mso-hlinkClick-tooltip"_ustr
, Any(sTooltip
));
1319 // Placeholder uses the height set on the slide instead of the height from the master slide,
1320 // if it has the "TextAutoGrowHeight" property
1321 if (getTextBody() && mxShape
->getShapeType().startsWith("com.sun.star.presentation."))
1323 bool bAutoGrowHeight
= getTextBody()
1324 ->getTextProperties()
1325 .maPropertyMap
.getProperty(PROP_TextAutoGrowHeight
)
1327 if (bAutoGrowHeight
)
1329 ppt::PowerPointImport
* pPPT
= dynamic_cast<ppt::PowerPointImport
*>(&rFilterBase
);
1330 if (!pPPT
->getActualSlidePersist()->isMasterPage())
1332 sal_Int32 nUpper
= 0;
1333 sal_Int32 nLower
= 0;
1334 sal_Int32 nHeight
= maSize
.Height
/ 360;
1335 if (getTextBody()->getTextProperties().moInsets
[1].has_value()
1336 && getTextBody()->getTextProperties().moInsets
[3].has_value())
1338 nUpper
= *getTextBody()->getTextProperties().moInsets
[1];
1339 nLower
= *getTextBody()->getTextProperties().moInsets
[3];
1343 maDefaultShapeProperties
.getProperty(PROP_TextUpperDistance
) >>= nUpper
;
1344 maDefaultShapeProperties
.getProperty(PROP_TextLowerDistance
) >>= nLower
;
1346 nHeight
-= (nUpper
+ nLower
);
1347 mxShape
->setSize(awt::Size(0, nHeight
));
1350 else // the placeholder uses the height set on the master slide
1351 mxShape
->setSize(awt::Size(0, 0));
1354 if (aServiceName
!= "com.sun.star.text.TextFrame")
1355 rxShapes
->add( mxShape
);
1357 if ( mbHidden
|| mbHiddenMasterShape
)
1359 SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId
<< "'");
1360 xSet
->setPropertyValue( u
"Visible"_ustr
, Any( false ) );
1361 // In Excel hidden means not printed, let's use visibility for now until that's handled separately
1362 xSet
->setPropertyValue( u
"Printable"_ustr
, Any( false ) );
1367 xSet
->setPropertyValue(u
"MoveProtect"_ustr
, Any(true));
1368 xSet
->setPropertyValue(u
"SizeProtect"_ustr
, Any(true));
1371 ActionLockGuard
const alg(mxShape
);
1373 // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape
1376 uno::Reference
< text::XText
> xText( mxShape
, uno::UNO_QUERY
);
1379 xText
->setString( u
""_ustr
);
1385 // the "EmbeddedObject" property is read-only, so we have to create
1386 // the shape first, and it can be read only after the shape is
1387 // inserted into the document, so delay the actual import until here
1388 SvGlobalName
name(SO3_SM_CLASSID
);
1389 xSet
->setPropertyValue(u
"CLSID"_ustr
, uno::Any(name
.GetHexName()));
1390 uno::Reference
<embed::XEmbeddedObject
> const xObj(
1391 xSet
->getPropertyValue(u
"EmbeddedObject"_ustr
), uno::UNO_QUERY
);
1394 uno::Reference
<uno::XInterface
> const xMathModel(xObj
->getComponent());
1395 oox::FormulaImExportBase
*const pMagic(
1396 dynamic_cast<oox::FormulaImExportBase
*>(xMathModel
.get()));
1398 pMagic
->readFormulaOoxml(*pMathXml
);
1402 const GraphicHelper
& rGraphicHelper
= rFilterBase
.getGraphicHelper();
1404 ::Color
nLinePhClr(ColorTransparency
, 0xffffffff);
1405 ::Color
nFillPhClr(ColorTransparency
, 0xffffffff);
1406 sal_Int16 nFillPhClrTheme
= -1;
1407 sal_Int16 nLinePhClrTheme
= -1;
1408 // TODO: use ph color when applying effect properties
1409 //sal_Int32 nEffectPhClr = -1;
1411 // dmapper needs the original rotation angle for calculating square wrap. This angle is not
1412 // available as property there, so store it in InteropGrabBag.
1413 putPropertyToGrabBag(u
"mso-rotation-angle"_ustr
, Any(mnRotation
));
1417 if( const ShapeStyleRef
* pLineRef
= getShapeStyleRef( XML_lnRef
) )
1419 LineProperties aLineProperties
;
1420 aLineProperties
.maLineFill
.moFillType
= XML_noFill
;
1421 if( const LineProperties
* pLineProps
= pTheme
->getLineStyle( pLineRef
->mnThemedIdx
) )
1422 aLineProperties
.assignUsed( *pLineProps
);
1423 nLinePhClr
= pLineRef
->maPhClr
.getColor( rGraphicHelper
);
1424 nLinePhClrTheme
= pLineRef
->maPhClr
.getSchemeColorIndex();
1426 // Store style-related properties to InteropGrabBag to be able to export them back
1427 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1429 {"SchemeClr", uno::Any(pLineRef
->maPhClr
.getSchemeColorName())},
1430 {"Idx", uno::Any(pLineRef
->mnThemedIdx
)},
1431 {"Color", uno::Any(nLinePhClr
)},
1432 {"LineStyle", uno::Any(aLineProperties
.getLineStyle())},
1433 {"LineCap", uno::Any(aLineProperties
.getLineCap())},
1434 {"LineJoint", uno::Any(aLineProperties
.getLineJoint())},
1435 {"LineWidth", uno::Any(aLineProperties
.getLineWidth())},
1436 {"Transformations", uno::Any(pLineRef
->maPhClr
.getTransformations())}
1438 putPropertyToGrabBag( u
"StyleLnRef"_ustr
, Any( aProperties
) );
1440 if( const ShapeStyleRef
* pFillRef
= getShapeStyleRef( XML_fillRef
) )
1442 if (!getFillProperties().moUseBgFill
.value_or(false))
1444 nFillPhClr
= pFillRef
->maPhClr
.getColor(rGraphicHelper
);
1445 nFillPhClrTheme
= pFillRef
->maPhClr
.getSchemeColorIndex();
1448 OUString sColorScheme
= pFillRef
->maPhClr
.getSchemeColorName();
1449 if( !sColorScheme
.isEmpty() )
1451 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1453 {"SchemeClr", uno::Any(sColorScheme
)},
1454 {"Idx", uno::Any(pFillRef
->mnThemedIdx
)},
1455 {"Color", uno::Any(nFillPhClr
)},
1456 {"Transformations", uno::Any(pFillRef
->maPhClr
.getTransformations())}
1459 putPropertyToGrabBag( u
"StyleFillRef"_ustr
, Any( aProperties
) );
1462 if( const ShapeStyleRef
* pEffectRef
= getShapeStyleRef( XML_effectRef
) )
1464 // TODO: use ph color when applying effect properties
1465 // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper );
1467 // Store style-related properties to InteropGrabBag to be able to export them back
1468 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1470 {"SchemeClr", uno::Any(pEffectRef
->maPhClr
.getSchemeColorName())},
1471 {"Idx", uno::Any(pEffectRef
->mnThemedIdx
)},
1472 {"Transformations", uno::Any(pEffectRef
->maPhClr
.getTransformations())}
1474 putPropertyToGrabBag( u
"StyleEffectRef"_ustr
, Any( aProperties
) );
1477 ShapePropertyMap
aShapeProps( rFilterBase
.getModelObjectHelper() );
1479 // add properties from textbody to shape properties
1482 // tdf#67347: In case of Stacked, PP calculates in the vertical direction with the
1483 // horizontal alignment.
1484 // In LO, we simulate it by setting TextVerticalAdjust based on the ParagraphAdjust
1485 // of the 1. paragraph
1486 // It is not perfect, because we have 1 TextVerticalAdjust / 1 shape, and it
1487 // does not support justified, while we can have many ParagraphAdjust / 1 shape
1488 // (if the shape have more paragraphs)
1489 if (mpTextBody
->getTextProperties().maPropertyMap
.hasProperty(PROP_WritingMode
)
1490 && mpTextBody
->getTextProperties().maPropertyMap
.getProperty(PROP_WritingMode
)
1491 == uno::Any(text::WritingMode2::STACKED
)
1492 && mpTextBody
->getParagraphs().size() > 0
1493 && aServiceName
!= "com.sun.star.drawing.GroupShape")
1495 std::optional
<css::style::ParagraphAdjust
>& oParaAdjust
1496 = mpTextBody
->getParagraphs()[0]->getProperties().getParaAdjust();
1500 switch (*oParaAdjust
)
1502 case ParagraphAdjust::ParagraphAdjust_LEFT
:
1503 mpTextBody
->getTextProperties().meVA
1504 = TextVerticalAdjust::TextVerticalAdjust_TOP
;
1506 case ParagraphAdjust::ParagraphAdjust_CENTER
:
1507 mpTextBody
->getTextProperties().meVA
1508 = TextVerticalAdjust::TextVerticalAdjust_CENTER
;
1510 case ParagraphAdjust::ParagraphAdjust_RIGHT
:
1511 mpTextBody
->getTextProperties().meVA
1512 = TextVerticalAdjust::TextVerticalAdjust_BOTTOM
;
1517 mpTextBody
->getTextProperties().maPropertyMap
.setProperty(
1518 PROP_TextVerticalAdjust
, mpTextBody
->getTextProperties().meVA
);
1522 // tdf#162571: In case of shapes with TextAutoGrowHeight, PP calculates/grow the
1523 // shapes size in edit mode (typing) based on the text horizontal alignment.
1524 // In LO, we simulate it by setting TextHorizontalAdjust based on the ParagraphAdjust
1525 // of the 1. paragraph
1526 // It is not perfect, because we have 1 TextHorizontalAdjust / 1 shape,
1527 // while we can have many ParagraphAdjust / 1 shape
1528 if (!mpTextBody
->getTextProperties().maPropertyMap
.hasProperty(PROP_WritingMode
)
1529 && mpTextBody
->getParagraphs().size() > 0)
1531 std::optional
<css::style::ParagraphAdjust
>& oParaAdjust
1532 = mpTextBody
->getParagraphs()[0]->getProperties().getParaAdjust();
1534 bool bAutoHeight
= false;
1535 Reference
< XPropertySetInfo
> xSetInfo(xSet
->getPropertySetInfo());
1536 const OUString
& rPropName
= PropertyMap::getPropertyName(PROP_TextAutoGrowHeight
);
1537 if (xSetInfo
.is() && xSetInfo
->hasPropertyByName(rPropName
))
1539 uno::Any aTextAutoGrowHeight
= xSet
->getPropertyValue(u
"TextAutoGrowHeight"_ustr
);
1540 aTextAutoGrowHeight
>>= bAutoHeight
;
1543 if (bAutoHeight
&& nShapeRotateInclCamera
== 0)
1545 mpTextBody
->getTextProperties().maPropertyMap
.setProperty(
1546 PROP_TextHorizontalAdjust
, lcl_convertTextAdjust(
1547 oParaAdjust
? *oParaAdjust
: ParagraphAdjust_LEFT
));
1551 mpTextBody
->getTextProperties().pushTextDistances(Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
));
1552 aShapeProps
.assignUsed( mpTextBody
->getTextProperties().maPropertyMap
);
1553 // Push char properties as well - specifically useful when this is a placeholder
1554 if( mpMasterTextListStyle
&& mpMasterTextListStyle
->getListStyle()[0].getTextCharacterProperties().moHeight
.has_value() )
1555 aShapeProps
.setProperty(PROP_CharHeight
, GetFontHeight( mpMasterTextListStyle
->getListStyle()[0].getTextCharacterProperties().moHeight
.value() ));
1558 // applying properties
1559 aShapeProps
.assignUsed( getShapeProperties() );
1560 aShapeProps
.assignUsed( maDefaultShapeProperties
);
1561 if(nShapeRotateInclCamera
!= 0 && bIsCustomShape
)
1562 aShapeProps
.setProperty(PROP_RotateAngle
,
1563 sal_Int32(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera
)));
1566 aServiceName
== "com.sun.star.drawing.GraphicObjectShape" ||
1567 aServiceName
== "com.sun.star.drawing.OLE2Shape")
1569 mpGraphicPropertiesPtr
->pushToPropMap( aShapeProps
, rGraphicHelper
, mbFlipH
, mbFlipV
);
1571 if ( mpTablePropertiesPtr
&& aServiceName
== "com.sun.star.drawing.TableShape" )
1573 mpTablePropertiesPtr
->pushToPropSet( rFilterBase
, xSet
, mpMasterTextListStyle
);
1574 if ( auto* pTableShape
= dynamic_cast<sdr::table::SdrTableObj
*>(SdrObject::getSdrObjectFromXShape(mxShape
)) )
1576 // Disable layouting until table height is expanded to fit the content
1577 pTableShape
->SetSkipChangeLayout(true);
1581 FillProperties aFillProperties
= getActualFillProperties(pTheme
, &rShapeOrParentShapeFillProps
);
1582 if (getFillProperties().moFillType
.has_value() && getFillProperties().moFillType
.value() == XML_grpFill
)
1583 getFillProperties().assignUsed(aFillProperties
);
1584 if(!bIsCroppedGraphic
&& !bIs3DGraphic
)
1585 aFillProperties
.pushToPropMap(aShapeProps
, rGraphicHelper
, mnRotation
, nFillPhClr
,
1586 css::awt::Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
),
1587 nFillPhClrTheme
, mbFlipH
, mbFlipV
, bIsCustomShape
);
1589 LineProperties aLineProperties
= getActualLineProperties(pTheme
);
1590 aLineProperties
.pushToPropMap( aShapeProps
, rGraphicHelper
, nLinePhClr
, nLinePhClrTheme
);
1591 EffectProperties aEffectProperties
= getActualEffectProperties(pTheme
);
1592 // TODO: use ph color when applying effect properties
1593 aEffectProperties
.pushToPropMap( aShapeProps
, rGraphicHelper
);
1595 // applying autogrowheight property before setting shape size, because
1596 // the shape size might be changed if currently autogrowheight is true
1597 // we must also check that the PropertySet supports the property.
1598 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
1599 const OUString
& rPropName
= PropertyMap::getPropertyName( PROP_TextAutoGrowHeight
);
1600 if( xSetInfo
.is() && xSetInfo
->hasPropertyByName( rPropName
) )
1601 if( aShapeProps
.hasProperty( PROP_TextAutoGrowHeight
) )
1602 xSet
->setPropertyValue( rPropName
, Any( false ) );
1604 // For extruded shapes, MSO uses the line color if no extrusion color is specified. LO uses
1605 // fill color in 'automatic' case. Thus we set extrusion color explicitly.
1606 if (bHas3DEffect
&& !aExtrusionColor
.isUsed())
1608 const OUString
& rFillColor2PropName
= PropertyMap::getPropertyName(PROP_FillColor2
);
1609 if (xSetInfo
.is() && xSetInfo
->hasPropertyByName(rFillColor2PropName
))
1611 Color aComplexColor
;
1612 if (aLineProperties
.maLineFill
.moFillType
.has_value()
1613 && aLineProperties
.maLineFill
.moFillType
.value() != XML_noFill
)
1614 aComplexColor
= aLineProperties
.maLineFill
.getBestSolidColor();
1615 else if (aFillProperties
.moFillType
.has_value()
1616 && aFillProperties
.moFillType
.value() != XML_noFill
)
1617 aComplexColor
= aFillProperties
.getBestSolidColor();
1618 if (aComplexColor
.isUsed())
1620 const ::Color aSimpleColor
= aComplexColor
.getColor(rFilterBase
.getGraphicHelper());
1621 xSet
->setPropertyValue(rFillColor2PropName
, Any(aSimpleColor
));
1626 // do not set properties at a group shape (this causes
1627 // assertions from svx) ...
1628 if( aServiceName
!= "com.sun.star.drawing.GroupShape" )
1630 if (aServiceName
== "com.sun.star.text.TextFrame")
1632 if (mpCustomShapePropertiesPtr
&& mpCustomShapePropertiesPtr
->getShapeTypeOverride())
1634 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1635 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1636 propertySet
->getPropertyValue(u
"FrameInteropGrabBag"_ustr
) >>= aGrabBag
;
1637 sal_Int32 length
= aGrabBag
.getLength();
1638 aGrabBag
.realloc( length
+1);
1639 auto pGrabBag
= aGrabBag
.getArray();
1640 pGrabBag
[length
].Name
= "mso-orig-shape-type";
1641 pGrabBag
[length
].Value
<<= mpCustomShapePropertiesPtr
->getShapePresetTypeName();
1642 propertySet
->setPropertyValue(u
"FrameInteropGrabBag"_ustr
,uno::Any(aGrabBag
));
1644 //If the text box has links then save the link information so that
1645 //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames.
1648 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1649 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1650 propertySet
->getPropertyValue(u
"FrameInteropGrabBag"_ustr
) >>= aGrabBag
;
1651 sal_Int32 length
= aGrabBag
.getLength();
1652 aGrabBag
.realloc( length
+ 3 );
1653 auto pGrabBag
= aGrabBag
.getArray();
1654 pGrabBag
[length
].Name
= "TxbxHasLink";
1655 pGrabBag
[length
].Value
<<= isLinkedTxbx();
1656 pGrabBag
[length
+ 1 ].Name
= "Txbx-Id";
1657 pGrabBag
[length
+ 1 ].Value
<<= getLinkedTxbxAttributes().id
;
1658 pGrabBag
[length
+ 2 ].Name
= "Txbx-Seq";
1659 pGrabBag
[length
+ 2 ].Value
<<= getLinkedTxbxAttributes().seq
;
1660 propertySet
->setPropertyValue(u
"FrameInteropGrabBag"_ustr
,uno::Any(aGrabBag
));
1663 // TextFrames have BackColor, not FillColor
1664 if (aShapeProps
.hasProperty(PROP_FillColor
))
1666 aShapeProps
.setAnyProperty(PROP_BackColor
, aShapeProps
.getProperty(PROP_FillColor
));
1667 aShapeProps
.erase(PROP_FillColor
);
1669 // TextFrames have BackColorTransparency, not FillTransparence
1670 if (aShapeProps
.hasProperty(PROP_FillTransparence
))
1672 aShapeProps
.setAnyProperty(PROP_BackColorTransparency
, aShapeProps
.getProperty(PROP_FillTransparence
));
1673 aShapeProps
.erase(PROP_FillTransparence
);
1675 // TextFrames have BackGraphic, not FillBitmap
1676 if (aShapeProps
.hasProperty(PROP_FillBitmap
))
1678 aShapeProps
.setAnyProperty(PROP_BackGraphic
, aShapeProps
.getProperty(PROP_FillBitmap
));
1679 aShapeProps
.erase(PROP_FillBitmap
);
1681 if (aShapeProps
.hasProperty(PROP_FillBitmapName
))
1683 uno::Any aAny
= aShapeProps
.getProperty(PROP_FillBitmapName
);
1684 OUString aFillBitmapName
= aAny
.get
<OUString
>();
1685 uno::Reference
<awt::XBitmap
> xBitmap
= rFilterBase
.getModelObjectHelper().getFillBitmap(aFillBitmapName
);
1686 uno::Reference
<graphic::XGraphic
> xGraphic(xBitmap
, uno::UNO_QUERY
);
1687 aShapeProps
.setProperty(PROP_BackGraphic
, xGraphic
);
1688 // aShapeProps.erase(PROP_FillBitmapName); // Maybe, leave the name as well
1690 // And no LineColor property; individual borders can have colors
1691 if (aShapeProps
.hasProperty(PROP_LineColor
))
1693 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
1694 static const sal_Int32 aBorders
[] =
1696 PROP_TopBorder
, PROP_LeftBorder
, PROP_BottomBorder
, PROP_RightBorder
1698 for (sal_Int32 nBorder
: aBorders
)
1700 css::table::BorderLine2 aBorderLine
= xPropertySet
->getPropertyValue(PropertyMap::getPropertyName(nBorder
)).get
<css::table::BorderLine2
>();
1701 aBorderLine
.Color
= aShapeProps
.getProperty(PROP_LineColor
).get
<sal_Int32
>();
1702 if (aLineProperties
.moLineWidth
.has_value())
1703 aBorderLine
.LineWidth
= convertEmuToHmm(aLineProperties
.moLineWidth
.value());
1704 aShapeProps
.setProperty(nBorder
, aBorderLine
);
1706 aShapeProps
.erase(PROP_LineColor
);
1710 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
1711 static constexpr OUString aGrabBagPropName
= u
"FrameInteropGrabBag"_ustr
;
1712 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1713 xPropertySet
->getPropertyValue(aGrabBagPropName
) >>= aGrabBag
;
1714 beans::PropertyValue
aPair(comphelper::makePropertyValue(u
"mso-rotation-angle"_ustr
,
1716 if (aGrabBag
.hasElements())
1718 sal_Int32 nLength
= aGrabBag
.getLength();
1719 aGrabBag
.realloc(nLength
+ 1);
1720 aGrabBag
.getArray()[nLength
] = std::move(aPair
);
1724 aGrabBag
= { std::move(aPair
) };
1726 xPropertySet
->setPropertyValue(aGrabBagPropName
, uno::Any(aGrabBag
));
1728 // TextFrames have ShadowFormat, not individual shadow properties.
1729 std::optional
<sal_Int32
> oShadowDistance
;
1730 if (aShapeProps
.hasProperty(PROP_ShadowXDistance
))
1732 oShadowDistance
= aShapeProps
.getProperty(PROP_ShadowXDistance
).get
<sal_Int32
>();
1733 aShapeProps
.erase(PROP_ShadowXDistance
);
1735 if (aShapeProps
.hasProperty(PROP_ShadowYDistance
))
1737 // There is a single 'dist' attribute, so no need to count the avg of x and y.
1738 aShapeProps
.erase(PROP_ShadowYDistance
);
1740 std::optional
<sal_Int32
> oShadowColor
;
1741 if (aShapeProps
.hasProperty(PROP_ShadowColor
))
1743 oShadowColor
= aShapeProps
.getProperty(PROP_ShadowColor
).get
<sal_Int32
>();
1744 aShapeProps
.erase(PROP_ShadowColor
);
1746 if (aShapeProps
.hasProperty(PROP_Shadow
))
1747 aShapeProps
.erase(PROP_Shadow
);
1749 if (oShadowDistance
|| oShadowColor
|| aEffectProperties
.maShadow
.moShadowDir
.has_value())
1751 css::table::ShadowFormat aFormat
;
1753 aFormat
.Color
= *oShadowColor
;
1754 if (aEffectProperties
.maShadow
.moShadowDir
.has_value())
1756 css::table::ShadowLocation nLocation
= css::table::ShadowLocation_NONE
;
1757 switch (aEffectProperties
.maShadow
.moShadowDir
.value())
1760 nLocation
= css::table::ShadowLocation_TOP_LEFT
;
1763 nLocation
= css::table::ShadowLocation_TOP_RIGHT
;
1766 nLocation
= css::table::ShadowLocation_BOTTOM_LEFT
;
1769 nLocation
= css::table::ShadowLocation_BOTTOM_RIGHT
;
1772 aFormat
.Location
= nLocation
;
1774 aFormat
.ShadowWidth
= *oShadowDistance
;
1775 aShapeProps
.setProperty(PROP_ShadowFormat
, aFormat
);
1781 // This introduces a TextBox in a shape in Writer. ToDo: Can we restrict it to cases
1782 // where the TextBox edit engine is really needed? tdf#82627
1783 aShapeProps
.setProperty(PROP_TextBox
, true);
1786 if (aServiceName
!= "com.sun.star.text.TextFrame" && isLinkedTxbx())
1788 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1789 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1790 propertySet
->getPropertyValue(u
"InteropGrabBag"_ustr
) >>= aGrabBag
;
1791 sal_Int32 length
= aGrabBag
.getLength();
1792 aGrabBag
.realloc( length
+ 3 );
1793 auto pGrabBag
= aGrabBag
.getArray();
1794 pGrabBag
[length
].Name
= "TxbxHasLink";
1795 pGrabBag
[length
].Value
<<= isLinkedTxbx();
1796 pGrabBag
[length
+ 1 ].Name
= "Txbx-Id";
1797 pGrabBag
[length
+ 1 ].Value
<<= getLinkedTxbxAttributes().id
;
1798 pGrabBag
[length
+ 2 ].Name
= "Txbx-Seq";
1799 pGrabBag
[length
+ 2 ].Value
<<= getLinkedTxbxAttributes().seq
;
1800 propertySet
->setPropertyValue(u
"InteropGrabBag"_ustr
,uno::Any(aGrabBag
));
1803 PropertySet( xSet
).setProperties( aShapeProps
);
1805 if (mpTablePropertiesPtr
&& aServiceName
== "com.sun.star.drawing.TableShape")
1807 // Powerpoint exports desired row heights (i.e. what user attempted to set it as, not how it appears visually)
1808 // Expand table height if there are rows that can't fit the content
1809 if (auto* pTableShape
= dynamic_cast<sdr::table::SdrTableObj
*>(SdrObject::getSdrObjectFromXShape(mxShape
)))
1811 tools::Rectangle aArea
{};
1812 pTableShape
->LayoutTableHeight(aArea
);
1813 sal_Int32 nCorrectedHeight
= aArea
.GetHeight();
1814 const auto aShapeSize
= mxShape
->getSize();
1815 if( nCorrectedHeight
> aShapeSize
.Height
)
1816 mxShape
->setSize( {aShapeSize
.Width
, nCorrectedHeight
} );
1817 pTableShape
->SetSkipChangeLayout(false);
1823 putPropertyToGrabBag( u
"LockedCanvas"_ustr
, Any( true ) );
1824 if (aServiceName
== "com.sun.star.drawing.LineShape")
1826 // It seems the position and size for lines inside a locked canvas is absolute.
1827 mxShape
->setPosition(awt::Point(aShapeRectHmm
.X
, aShapeRectHmm
.Y
));
1828 mxShape
->setSize(awt::Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
));
1832 if (mbWordprocessingCanvas
)
1834 putPropertyToGrabBag(u
"WordprocessingCanvas"_ustr
, Any(true));
1837 // Store original fill and line colors of the shape and the theme color name to InteropGrabBag
1838 std::vector
<beans::PropertyValue
> aProperties
1840 comphelper::makePropertyValue(u
"EmuLineWidth"_ustr
, aLineProperties
.moLineWidth
.value_or(0)),
1841 comphelper::makePropertyValue(u
"OriginalSolidFillClr"_ustr
, aShapeProps
.getProperty(PROP_FillColor
)),
1842 comphelper::makePropertyValue(u
"OriginalLnSolidFillClr"_ustr
, aShapeProps
.getProperty(PROP_LineColor
))
1844 OUString sColorFillScheme
= aFillProperties
.maFillColor
.getSchemeColorName();
1845 if( !aFillProperties
.maFillColor
.isPlaceHolder() && !sColorFillScheme
.isEmpty() )
1847 aProperties
.push_back(comphelper::makePropertyValue(u
"SpPrSolidFillSchemeClr"_ustr
, sColorFillScheme
));
1848 aProperties
.push_back(comphelper::makePropertyValue(u
"SpPrSolidFillSchemeClrTransformations"_ustr
, aFillProperties
.maFillColor
.getTransformations()));
1850 OUString sLnColorFillScheme
= aLineProperties
.maLineFill
.maFillColor
.getSchemeColorName();
1851 if( !aLineProperties
.maLineFill
.maFillColor
.isPlaceHolder() && !sLnColorFillScheme
.isEmpty() )
1853 aProperties
.push_back(comphelper::makePropertyValue(u
"SpPrLnSolidFillSchemeClr"_ustr
, sLnColorFillScheme
));
1854 auto aResolvedSchemeClr
= aLineProperties
.maLineFill
.maFillColor
;
1855 aResolvedSchemeClr
.clearTransformations();
1856 aProperties
.push_back(comphelper::makePropertyValue(u
"SpPrLnSolidFillResolvedSchemeClr"_ustr
, aResolvedSchemeClr
.getColor(rGraphicHelper
, nFillPhClr
)));
1857 aProperties
.push_back(comphelper::makePropertyValue(u
"SpPrLnSolidFillSchemeClrTransformations"_ustr
, aLineProperties
.maLineFill
.maFillColor
.getTransformations()));
1859 putPropertiesToGrabBag(comphelper::containerToSequence(aProperties
));
1861 // Store original gradient fill of the shape to InteropGrabBag
1862 // LibreOffice doesn't support all the kinds of gradient so we save its complete definition
1863 if( aShapeProps
.hasProperty( PROP_FillGradient
) )
1865 std::vector
<beans::PropertyValue
> aGradientStops
;
1867 for( const auto& [rPos
, rColor
] : aFillProperties
.maGradientProps
.maGradientStops
)
1868 { // for each stop in the gradient definition:
1871 std::vector
<beans::PropertyValue
> aGradientStop
1873 comphelper::makePropertyValue(u
"Pos"_ustr
, rPos
)
1876 OUString sStopColorScheme
= rColor
.getSchemeColorName();
1877 if( sStopColorScheme
.isEmpty() )
1880 aGradientStop
.push_back(comphelper::makePropertyValue(u
"RgbClr"_ustr
, rColor
.getColor(rGraphicHelper
, nFillPhClr
)));
1881 // in the case of a RGB color, transformations are already applied to
1882 // the color with the exception of alpha transformations. We only need
1883 // to keep the transparency value to calculate the alpha value later.
1884 if( rColor
.hasTransparency() )
1885 aGradientStop
.push_back(comphelper::makePropertyValue(u
"Transparency"_ustr
, rColor
.getTransparency()));
1889 // save color with scheme name
1890 aGradientStop
.push_back(comphelper::makePropertyValue(u
"SchemeClr"_ustr
, sStopColorScheme
));
1891 // save all color transformations
1892 aGradientStop
.push_back(comphelper::makePropertyValue(u
"Transformations"_ustr
, rColor
.getTransformations()));
1895 aGradientStops
.push_back(comphelper::makePropertyValue(OUString::number(i
), comphelper::containerToSequence(aGradientStop
)));
1898 // If getFillProperties.moFillType is unused that means gradient is defined by a theme
1899 // which is already saved into StyleFillRef property, so no need to save the explicit values too
1900 if( getFillProperties().moFillType
.has_value() )
1901 putPropertyToGrabBag( u
"GradFillDefinition"_ustr
, uno::Any(comphelper::containerToSequence(aGradientStops
)));
1902 putPropertyToGrabBag( u
"OriginalGradFill"_ustr
, aShapeProps
.getProperty(PROP_FillGradient
) );
1905 // store unsupported effect attributes in the grab bag
1906 if (!aEffectProperties
.m_Effects
.empty())
1908 std::vector
<beans::PropertyValue
> aEffects
;
1909 for (auto const& it
: aEffectProperties
.m_Effects
)
1911 PropertyValue aEffect
= it
->getEffect();
1912 if( !aEffect
.Name
.isEmpty() )
1914 std::vector
<beans::PropertyValue
> aEffectsGrabBag
1916 comphelper::makePropertyValue(u
"Attribs"_ustr
, aEffect
.Value
)
1919 Color
& aColor( it
->moColor
);
1920 OUString sColorScheme
= aColor
.getSchemeColorName();
1921 if( sColorScheme
.isEmpty() )
1923 // RGB color and transparency value
1924 aEffectsGrabBag
.push_back(comphelper::makePropertyValue(u
"RgbClr"_ustr
, aColor
.getColor(rGraphicHelper
, nFillPhClr
)));
1925 aEffectsGrabBag
.push_back(comphelper::makePropertyValue(u
"RgbClrTransparency"_ustr
, aColor
.getTransparency()));
1929 // scheme color with name and transformations
1930 aEffectsGrabBag
.push_back(comphelper::makePropertyValue(u
"SchemeClr"_ustr
, sColorScheme
));
1931 aEffectsGrabBag
.push_back(comphelper::makePropertyValue(u
"SchemeClrTransformations"_ustr
, aColor
.getTransformations()));
1933 aEffects
.push_back(comphelper::makePropertyValue(aEffect
.Name
, comphelper::containerToSequence(aEffectsGrabBag
)));
1936 putPropertyToGrabBag(u
"EffectProperties"_ustr
, uno::Any(comphelper::containerToSequence(aEffects
)));
1939 // add 3D effects if any to GrabBag. They are still used in export.
1940 Sequence
< PropertyValue
> aCamera3DEffects
= get3DProperties().getCameraAttributes();
1941 Sequence
< PropertyValue
> aLightRig3DEffects
= get3DProperties().getLightRigAttributes();
1942 Sequence
< PropertyValue
> aShape3DEffects
= get3DProperties().getShape3DAttributes( rGraphicHelper
, nFillPhClr
);
1943 if( aCamera3DEffects
.hasElements() || aLightRig3DEffects
.hasElements() || aShape3DEffects
.hasElements() )
1945 uno::Sequence
<beans::PropertyValue
> a3DEffectsGrabBag
= comphelper::InitPropertySequence(
1947 {"Camera", uno::Any(aCamera3DEffects
)},
1948 {"LightRig", uno::Any(aLightRig3DEffects
)},
1949 {"Shape3D", uno::Any(aShape3DEffects
)}
1951 putPropertyToGrabBag( u
"3DEffectProperties"_ustr
, Any( a3DEffectsGrabBag
) );
1954 if( bIsCustomShape
&& getTextBody())
1957 Sequence
< PropertyValue
> aTextCamera3DEffects
= getTextBody()->get3DProperties().getCameraAttributes();
1958 Sequence
< PropertyValue
> aTextLightRig3DEffects
= getTextBody()->get3DProperties().getLightRigAttributes();
1959 Sequence
< PropertyValue
> aTextShape3DEffects
= getTextBody()->get3DProperties().getShape3DAttributes( rGraphicHelper
, nFillPhClr
);
1960 if( aTextCamera3DEffects
.hasElements() || aTextLightRig3DEffects
.hasElements() || aTextShape3DEffects
.hasElements() )
1962 uno::Sequence
<beans::PropertyValue
> aText3DEffectsGrabBag
= comphelper::InitPropertySequence(
1964 {"Camera", uno::Any(aTextCamera3DEffects
)},
1965 {"LightRig", uno::Any(aTextLightRig3DEffects
)},
1966 {"Shape3D", uno::Any(aTextShape3DEffects
)}
1968 putPropertyToGrabBag( u
"Text3DEffectProperties"_ustr
, Any( aText3DEffectsGrabBag
) );
1972 // store bitmap artistic effects in the grab bag
1973 if( !mpGraphicPropertiesPtr
->maBlipProps
.maEffect
.isEmpty() )
1974 putPropertyToGrabBag( u
"ArtisticEffectProperties"_ustr
,
1975 Any( mpGraphicPropertiesPtr
->maBlipProps
.maEffect
.getEffect() ) );
1978 else if( mbLockedCanvas
)
1980 //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas
1981 putPropertyToGrabBag( u
"LockedCanvas"_ustr
, Any( true ) );
1983 else if (mbWordprocessingCanvas
)
1985 putPropertyToGrabBag(u
"WordprocessingCanvas"_ustr
, Any(true));
1986 putPropertyToGrabBag(u
"mso-edit-as"_ustr
, Any(u
"canvas"_ustr
)); // for export VML Fallback
1989 // These can have a custom geometry, so position should be set here,
1990 // after creation but before custom shape handling, using the position
1991 // we got from the caller.
1992 if (mbWps
&& aServiceName
== "com.sun.star.drawing.LineShape" && !pParentGroupShape
)
1993 mxShape
->setPosition(maPosition
);
1995 if (bIsConnectorShape
)
1997 msConnectorName
= mpCustomShapePropertiesPtr
->getShapePresetTypeName();
1999 const auto& aAdjustmentList
= mpCustomShapePropertiesPtr
->getAdjustmentGuideList();
2000 for (size_t i
= 0; i
< aAdjustmentList
.size(); i
++)
2001 maConnectorAdjustmentList
.push_back(aAdjustmentList
[i
].maFormula
);
2003 sal_Int32 nType
= mpCustomShapePropertiesPtr
->getShapePresetType();
2007 case XML_straightConnector1
:
2008 xSet
->setPropertyValue(u
"EdgeKind"_ustr
, Any(ConnectorType_LINE
));
2010 case XML_bentConnector2
:
2011 case XML_bentConnector3
:
2012 case XML_bentConnector4
:
2013 case XML_bentConnector5
:
2014 xSet
->setPropertyValue(u
"EdgeKind"_ustr
, Any(ConnectorType_STANDARD
));
2016 case XML_curvedConnector2
:
2017 case XML_curvedConnector3
:
2018 case XML_curvedConnector4
:
2019 case XML_curvedConnector5
:
2020 xSet
->setPropertyValue(u
"EdgeKind"_ustr
, Any(ConnectorType_CURVE
));
2027 if( bIsCustomShape
)
2030 mpCustomShapePropertiesPtr
->setMirroredX( true );
2032 mpCustomShapePropertiesPtr
->setMirroredY( true );
2035 sal_Int32 nTextCameraZRotation
= getTextBody()->get3DProperties().maCameraRotation
.mnRevolution
.value_or(0);
2036 mpCustomShapePropertiesPtr
->setTextCameraZRotateAngle( nTextCameraZRotation
/ 60000 );
2038 // TextPreRotateAngle. Text rotates inside the text area. Might be used for diagram layout 'upr' and 'grav'.
2039 sal_Int32 nTextPreRotateAngle
= static_cast< sal_Int32
>( getTextBody()->getTextProperties().moTextPreRotation
.value_or( 0 ) );
2041 nTextPreRotateAngle
-= mnDiagramRotation
; // Use of mnDiagramRotation is unclear. It seems to be always 0 here.
2043 // TextRotateAngle. The text area rotates.
2044 sal_Int32 nTextAreaRotateAngle
= getTextBody()->getTextProperties().moTextAreaRotation
.value_or(0);
2045 if (getTextBody()->getTextProperties().moUpright
)
2047 // When upright is set, any text area transformation and shape rotation is ignored
2048 // in MS Office. To simulate this behaviour, we rotate the text area into the
2049 // opposite direction of the shape rotation by as much as the shape was rotated
2050 // and so compensate the shape rotation, which is added in rendering.
2051 nTextAreaRotateAngle
= -mnRotation
;
2052 // If 45° <= shape rotation < 135° or 225° <= shape rotation < 315°,
2053 // then MS Office adds an additional 90° rotation to the text area.
2054 const sal_Int32
nDeg(mnRotation
/ 60000);
2055 if ((nDeg
>= 45 && nDeg
< 135) || (nDeg
>= 225 && nDeg
< 315))
2057 nTextAreaRotateAngle
+= 5400000;
2058 nTextPreRotateAngle
-= 5400000; // compensate the additional text area rotation
2060 putPropertyToGrabBag(u
"Upright"_ustr
, Any(true));
2062 /* OOX measures text rotation clockwise in 1/60000th degrees,
2063 relative to the containing shape. set*Angle wants degrees counter-clockwise. */
2064 mpCustomShapePropertiesPtr
->setTextPreRotateAngle(-nTextPreRotateAngle
/ 60000);
2065 if (nTextAreaRotateAngle
!= 0)
2066 mpCustomShapePropertiesPtr
->setTextAreaRotateAngle(-nTextAreaRotateAngle
/ 60000);
2068 auto sHorzOverflow
= getTextBody()->getTextProperties().msHorzOverflow
;
2069 if (!sHorzOverflow
.isEmpty())
2070 putPropertyToGrabBag(u
"horzOverflow"_ustr
, uno::Any(getTextBody()->getTextProperties().msHorzOverflow
));
2071 if (XML_ellipsis
== getTextBody()->getTextProperties().moVertOverflow
)
2072 putPropertyToGrabBag(u
"vertOverflow"_ustr
, uno::Any(u
"ellipsis"_ustr
));
2075 // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks
2076 // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs
2077 SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName
<< "'");
2078 SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName
<< "'");
2080 mpCustomShapePropertiesPtr
->pushToPropSet(xSet
, maSize
);
2083 if (mpTextBody
&& !mpTextBody
->getTextProperties().msPrst
.isEmpty()
2084 && mpTextBody
->getTextProperties().msPrst
!= u
"textNoShape")
2086 bool bFromWordArt(aShapeProps
.hasProperty(PROP_FromWordArt
)
2087 ? aShapeProps
.getProperty(PROP_FromWordArt
).get
<bool>()
2089 FontworkHelpers::putCustomShapeIntoTextPathMode(
2090 mxShape
, mpCustomShapePropertiesPtr
, mpTextBody
->getTextProperties().msPrst
,
2094 else if( getTextBody() )
2095 getTextBody()->getTextProperties().pushVertSimulation();
2097 // tdf#133037: a bit hackish: force Shape to rotate in the opposite direction the camera would rotate
2098 PropertySet
aPropertySet(mxShape
);
2099 if ( !bUseRotationTransform
&& (nShapeRotateInclCamera
!=0) )
2101 Degree100
nAngle(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera
));
2102 aPropertySet
.setAnyProperty(PROP_RotateAngle
, Any( sal_Int32(nAngle
)));
2103 aPropertySet
.setAnyProperty( PROP_HoriOrientPosition
, Any( maPosition
.X
) );
2104 aPropertySet
.setAnyProperty( PROP_VertOrientPosition
, Any( maPosition
.Y
) );
2107 // Make sure to not set text to placeholders. Doing it here would eventually call
2108 // SvxTextEditSourceImpl::UpdateData, SdrObject::SetEmptyPresObj(false), and that
2109 // would make the object behave like a standard outline object.
2110 // TODO/FIXME: support custom prompt text in placeholders.
2111 if (rServiceName
== "com.sun.star.presentation.GraphicObjectShape")
2114 // in some cases, we don't have any text body.
2115 if( mpTextBody
&& ( !bDoNotInsertEmptyTextBody
|| !mpTextBody
->isEmpty() ) )
2117 Reference
< XText
> xText( mxShape
, UNO_QUERY
);
2118 if ( xText
.is() ) // not every shape is supporting an XText interface (e.g. GroupShape)
2120 TextCharacterProperties aCharStyleProperties
;
2121 if( const ShapeStyleRef
* pFontRef
= getShapeStyleRef( XML_fontRef
) )
2123 if( pFontRef
->mnThemedIdx
!= 0 )
2126 if( const TextCharacterProperties
* pCharProps
= pTheme
->getFontStyle( pFontRef
->mnThemedIdx
) )
2127 aCharStyleProperties
.assignUsed( *pCharProps
);
2128 SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color");
2129 if ( pFontRef
->maPhClr
.isUsed() )
2131 aCharStyleProperties
.maFillProperties
.maFillColor
= pFontRef
->maPhClr
;
2132 aCharStyleProperties
.maFillProperties
.moFillType
= XML_solidFill
;
2136 xText
->setString(u
""_ustr
);
2137 Reference
< XTextCursor
> xAt
= xText
->createTextCursor();
2138 getTextBody()->insertAt( rFilterBase
, xText
, xAt
, aCharStyleProperties
, mpMasterTextListStyle
);
2140 const TextParagraphVector
& rParagraphs
= getTextBody()->getParagraphs();
2141 if (!rParagraphs
.empty())
2143 const std::shared_ptr
<TextParagraph
>& pParagraph
= rParagraphs
[0];
2144 if (pParagraph
->getProperties().getParaAdjust())
2146 style::ParagraphAdjust eAdjust
= *pParagraph
->getProperties().getParaAdjust();
2147 if (eAdjust
== style::ParagraphAdjust_CENTER
)
2149 // If the first paragraph is centered, then set the para adjustment of
2150 // the shape itself to centered as well.
2151 aPropertySet
.setAnyProperty(PROP_ParaAdjust
, uno::Any(eAdjust
));
2155 // tdf#144092 For empty textboxes push character styles &
2156 // endParaRPr into the Shape's properties
2157 if (rParagraphs
.size() == 1 && pParagraph
->getRuns().empty())
2159 TextCharacterProperties aTextCharacterProps
{ pParagraph
->getCharacterStyle(
2160 aCharStyleProperties
, *mpMasterTextListStyle
,
2161 getTextBody()->getTextListStyle()) };
2162 aTextCharacterProps
.assignUsed(pParagraph
->getEndProperties());
2163 aTextCharacterProps
.pushToPropSet(aPropertySet
, rFilterBase
);
2167 // MS Office has e.g. fill and stroke of WordArt in the character properties,
2168 // LibreOffice uses shape properties.
2169 if (!mpTextBody
->getTextProperties().msPrst
.isEmpty()
2170 && mpTextBody
->getTextProperties().msPrst
!= u
"textNoShape")
2172 lcl_copyCharPropsToShape(mxShape
, mpTextBody
, rFilterBase
);
2178 // No drawingML text, but WPS text is expected: save the theme
2179 // character color on the shape, then.
2180 if(const ShapeStyleRef
* pFontRef
= getShapeStyleRef(XML_fontRef
))
2182 ::Color nCharColor
= pFontRef
->maPhClr
.getColor(rGraphicHelper
);
2183 aPropertySet
.setAnyProperty(PROP_CharColor
, uno::Any(nCharColor
));
2187 // Set glow effect properties
2188 if (aEffectProperties
.maGlow
.moGlowRad
.has_value()
2189 && aServiceName
!= "com.sun.star.drawing.GroupShape")
2191 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
2192 propertySet
->setPropertyValue(u
"GlowEffectRadius"_ustr
, Any(convertEmuToHmm(aEffectProperties
.maGlow
.moGlowRad
.value())));
2193 propertySet
->setPropertyValue(u
"GlowEffectColor"_ustr
, Any(aEffectProperties
.maGlow
.moGlowColor
.getColor(rGraphicHelper
)));
2194 propertySet
->setPropertyValue(u
"GlowEffectTransparency"_ustr
, Any(aEffectProperties
.maGlow
.moGlowColor
.getTransparency()));
2197 // Set soft edge effect properties
2198 if (aEffectProperties
.maSoftEdge
.moRad
.has_value())
2200 uno::Reference
<beans::XPropertySet
> propertySet(mxShape
, uno::UNO_QUERY
);
2201 propertySet
->setPropertyValue(
2202 u
"SoftEdgeRadius"_ustr
, Any(convertEmuToHmm(aEffectProperties
.maSoftEdge
.moRad
.value())));
2205 // Set text glow effect for shapes
2206 if (mpTextBody
&& (!bDoNotInsertEmptyTextBody
|| !mpTextBody
->isEmpty()))
2208 const TextParagraphVector
& rParagraphs
= mpTextBody
->getParagraphs();
2209 if (!rParagraphs
.empty())
2211 EffectProperties aTextEffectProperties
;
2212 for (TextParagraphVector::const_iterator aPIt
= rParagraphs
.begin(), aPEnd
= rParagraphs
.end(); aPIt
!= aPEnd
; ++aPIt
)
2214 const TextParagraph
& rTextPara
= **aPIt
;
2215 const TextCharacterProperties
& rParaProps
= rTextPara
.getProperties().getTextCharacterProperties();
2216 if (rParaProps
.getEffectProperties().maGlow
.moGlowRad
.has_value())
2218 aTextEffectProperties
.assignUsed(rParaProps
.getEffectProperties());
2223 for (TextRunVector::const_iterator aRIt
= rTextPara
.getRuns().begin(), aREnd
= rTextPara
.getRuns().end(); aRIt
!= aREnd
; ++aRIt
)
2225 const TextRun
& rTextRun
= **aRIt
;
2226 const TextCharacterProperties
& rRunrops
= rTextRun
.getTextCharacterProperties();
2227 if (rRunrops
.getEffectProperties().maGlow
.moGlowRad
.has_value())
2229 aTextEffectProperties
.assignUsed(rRunrops
.getEffectProperties());
2237 if (aTextEffectProperties
.maGlow
.moGlowRad
.has_value())
2239 xSet
->setPropertyValue(u
"GlowTextEffectRadius"_ustr
,
2240 uno::Any(convertEmuToHmm(aTextEffectProperties
.maGlow
.moGlowRad
.value())));
2241 xSet
->setPropertyValue(u
"GlowTextEffectColor"_ustr
,
2242 uno::Any(aTextEffectProperties
.maGlow
.moGlowColor
.getColor(rGraphicHelper
)));
2243 xSet
->setPropertyValue(u
"GlowTextEffectTransparency"_ustr
,
2244 uno::Any(aTextEffectProperties
.maGlow
.moGlowColor
.getTransparency()));
2249 // Set the stroke and fill-color properties of the OLE shape
2250 if (aServiceName
== "com.sun.star.drawing.OLE2Shape" && mxOleObjectInfo
2251 && !mxOleObjectInfo
->maShapeId
.isEmpty())
2252 if (::oox::vml::Drawing
* pVmlDrawing
= rFilterBase
.getVmlDrawing())
2253 if (const ::oox::vml::ShapeBase
* pVmlShape
2254 = pVmlDrawing
->getShapes().getShapeById(mxOleObjectInfo
->maShapeId
))
2256 // Apply stroke props from the type model of the related VML shape.
2257 ShapePropertyMap
aPropMap(rFilterBase
.getModelObjectHelper());
2258 pVmlShape
->getTypeModel().maStrokeModel
.pushToPropMap(
2259 aPropMap
, rFilterBase
.getGraphicHelper());
2260 // And, fill-color properties as well...
2261 pVmlShape
->getTypeModel().maFillModel
.pushToPropMap(
2262 aPropMap
, rFilterBase
.getGraphicHelper());
2263 PropertySet(xSet
).setProperties(aPropMap
);
2269 finalizeXShape( rFilterBase
, rxShapes
);
2273 // tdf#151518. The method readjustTextDistances is fix for tdf#148321, but conflicts with
2274 // text position in some of the SmartArt types in Writer. So exclude Writer here.
2275 OUString sDocumentService
;
2276 rFilterBase
.getMediaDescriptor()[utl::MediaDescriptor::PROP_DOCUMENTSERVICE
] >>= sDocumentService
;
2277 if (sDocumentService
!= u
"com.sun.star.text.TextDocument")
2278 mpTextBody
->getTextProperties().readjustTextDistances(mxShape
);
2280 // tdf#156857: ooxml files can have shape size with spAutoFit=true and the first priority of
2281 // shape size is the fix size even if TextAutoGrowHeight is true.
2282 bool bAutoHeight
= false;
2283 Reference
< XPropertySetInfo
> xSetInfo(xSet
->getPropertySetInfo());
2284 const OUString
& rPropName
= PropertyMap::getPropertyName(PROP_TextAutoGrowHeight
);
2285 if (xSetInfo
.is() && xSetInfo
->hasPropertyByName(rPropName
))
2287 uno::Any aTextAutoGrowHeight
= xSet
->getPropertyValue(u
"TextAutoGrowHeight"_ustr
);
2288 aTextAutoGrowHeight
>>= bAutoHeight
;
2291 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(mxShape
);
2292 if (pShape
&& bAutoHeight
&& bIsCustomShape
)
2294 tools::Rectangle
aOrigSize(aShapeRectHmm
.X
, aShapeRectHmm
.Y
,
2295 aShapeRectHmm
.X
+ aShapeRectHmm
.Width
, aShapeRectHmm
.Y
+ aShapeRectHmm
.Height
);
2296 tools::Rectangle aAdaptSize
= pShape
->GetLogicRect();
2297 // a little tolerance same as in \svx\source\svdraw\svdoashp.cxx:AdjustTextFrameWidthAndHeight
2298 if (std::abs(aOrigSize
.GetHeight() - aAdaptSize
.GetHeight()) > 1)
2300 aAdaptSize
.setHeight(aOrigSize
.GetHeight());
2301 pShape
->NbcSetLogicRect(aAdaptSize
, false);
2309 void Shape::keepDiagramDrawing(XmlFilterBase
& rFilterBase
, const OUString
& rFragmentPath
)
2312 sal_Int32 length
= maDiagramDoms
.getLength();
2313 maDiagramDoms
.realloc(length
+ 1);
2315 // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships
2316 uno::Sequence
<uno::Any
> diagramDrawing
{
2317 uno::Any(rFilterBase
.importFragment(rFragmentPath
)),
2318 uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase
, rFragmentPath
, u
"image"))
2321 beans::PropertyValue
* pValue
= maDiagramDoms
.getArray();
2322 pValue
[length
].Name
= "OOXDrawing";
2323 pValue
[length
].Value
<<= diagramDrawing
;
2326 void Shape::keepDiagramCompatibilityInfo()
2330 if( !maDiagramDoms
.hasElements() )
2333 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY_THROW
);
2334 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
2335 if ( !xSetInfo
.is() )
2338 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2339 if( !xSetInfo
->hasPropertyByName( aGrabBagPropName
) )
2342 Sequence
< PropertyValue
> aGrabBag
;
2343 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2345 // We keep the previous items, if present
2346 if ( aGrabBag
.hasElements() )
2347 xSet
->setPropertyValue( aGrabBagPropName
, Any( comphelper::concatSequences(aGrabBag
, maDiagramDoms
) ) );
2349 xSet
->setPropertyValue( aGrabBagPropName
, Any( maDiagramDoms
) );
2351 catch( const Exception
& )
2353 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::keepDiagramCompatibilityInfo" );
2357 void Shape::convertSmartArtToMetafile(XmlFilterBase
const & rFilterBase
)
2361 Reference
<XPropertySet
> xSet(mxShape
, UNO_QUERY_THROW
);
2363 xSet
->setPropertyValue(u
"MoveProtect"_ustr
, Any(true));
2364 xSet
->setPropertyValue(u
"SizeProtect"_ustr
, Any(true));
2366 // Replace existing shapes with a new Graphic Object rendered
2368 Reference
<XShape
> xShape(renderDiagramToGraphic(rFilterBase
));
2369 Reference
<XShapes
> xShapes(mxShape
, UNO_QUERY_THROW
);
2370 tools::Rectangle aBackgroundRect
2371 = SdrObject::getSdrObjectFromXShape(
2372 Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
))
2374 while (xShapes
->hasElements())
2375 xShapes
->remove(Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
));
2376 xShapes
->add(xShape
);
2377 SdrObject::getSdrObjectFromXShape(
2378 Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
))
2379 ->NbcSetLogicRect(aBackgroundRect
);
2381 catch (const Exception
&)
2383 TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile");
2387 Reference
< XShape
> Shape::renderDiagramToGraphic( XmlFilterBase
const & rFilterBase
)
2389 Reference
< XShape
> xShape
;
2393 if( !maDiagramDoms
.hasElements() )
2396 // Stream in which to place the rendered shape
2397 SvMemoryStream aTempStream
;
2398 Reference
< io::XStream
> xStream( new utl::OStreamWrapper( aTempStream
) );
2399 Reference
< io::XOutputStream
> xOutputStream( xStream
->getOutputStream() );
2401 // Size of the rendering
2402 awt::Size aActualSize
= mxShape
->getSize();
2403 Size
aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM
)));
2404 double fPixelsPer100thmm
= static_cast < double > ( aResolution
.Width() ) / 100000.0;
2405 awt::Size
aSize( static_cast < sal_Int32
> ( ( fPixelsPer100thmm
* aActualSize
.Width
) + 0.5 ),
2406 static_cast < sal_Int32
> ( ( fPixelsPer100thmm
* aActualSize
.Height
) + 0.5 ) );
2408 Sequence
< PropertyValue
> aFilterData
{
2409 comphelper::makePropertyValue(u
"PixelWidth"_ustr
, aSize
.Width
),
2410 comphelper::makePropertyValue(u
"PixelHeight"_ustr
, aSize
.Height
),
2411 comphelper::makePropertyValue(u
"LogicalWidth"_ustr
, aActualSize
.Width
),
2412 comphelper::makePropertyValue(u
"LogicalHeight"_ustr
, aActualSize
.Height
)
2415 Sequence
< PropertyValue
> aDescriptor
{
2416 comphelper::makePropertyValue(u
"OutputStream"_ustr
, xOutputStream
),
2417 comphelper::makePropertyValue(u
"FilterName"_ustr
, u
"SVM"_ustr
), // Rendering format
2418 comphelper::makePropertyValue(u
"FilterData"_ustr
, aFilterData
)
2421 Reference
< lang::XComponent
> xSourceDoc( mxShape
, UNO_QUERY_THROW
);
2422 Reference
< XGraphicExportFilter
> xGraphicExporter
= GraphicExportFilter::create( rFilterBase
.getComponentContext() );
2423 xGraphicExporter
->setSourceDocument( xSourceDoc
);
2424 xGraphicExporter
->filter( aDescriptor
);
2426 aTempStream
.Seek( STREAM_SEEK_TO_BEGIN
);
2429 GraphicFilter aFilter
;
2430 if ( aFilter
.ImportGraphic( aGraphic
, u
"", aTempStream
, GRFILTER_FORMAT_NOTFOUND
, nullptr, GraphicFilterImportFlags::NONE
) != ERRCODE_NONE
)
2432 SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" );
2436 Reference
< graphic::XGraphic
> xGraphic( aGraphic
.GetXGraphic() );
2437 Reference
< lang::XMultiServiceFactory
> xServiceFact( rFilterBase
.getModel(), UNO_QUERY_THROW
);
2438 xShape
.set( xServiceFact
->createInstance( u
"com.sun.star.drawing.GraphicObjectShape"_ustr
), UNO_QUERY_THROW
);
2439 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY_THROW
);
2440 xPropSet
->setPropertyValue( u
"Graphic"_ustr
, Any( xGraphic
) );
2441 xPropSet
->setPropertyValue( u
"MoveProtect"_ustr
, Any( true ) );
2442 xPropSet
->setPropertyValue( u
"SizeProtect"_ustr
, Any( true ) );
2443 xPropSet
->setPropertyValue( u
"Name"_ustr
, Any( u
"RenderedShapes"_ustr
) );
2445 catch( const Exception
& )
2447 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" );
2453 void Shape::setTextBody(const TextBodyPtr
& pTextBody
)
2455 mpTextBody
= pTextBody
;
2458 void Shape::setMasterTextListStyle( const TextListStylePtr
& pMasterTextListStyle
)
2460 SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId
<< "'");
2462 mpMasterTextListStyle
= pMasterTextListStyle
;
2465 OUString
Shape::finalizeServiceName( XmlFilterBase
& rFilter
, const OUString
& rServiceName
, const awt::Rectangle
& rShapeRect
)
2467 OUString aServiceName
= rServiceName
;
2468 switch( meFrameType
)
2470 case FRAMETYPE_OLEOBJECT
:
2472 awt::Size
aOleSize( rShapeRect
.Width
, rShapeRect
.Height
);
2473 if( rFilter
.getOleObjectHelper().importOleObject( maShapeProperties
, *mxOleObjectInfo
, aOleSize
) )
2474 aServiceName
= "com.sun.star.drawing.OLE2Shape";
2476 // get the path to the representation graphic
2477 OUString aGraphicPath
;
2478 if( !mxOleObjectInfo
->maShapeId
.isEmpty() )
2479 if( ::oox::vml::Drawing
* pVmlDrawing
= rFilter
.getVmlDrawing() )
2480 if( const ::oox::vml::ShapeBase
* pVmlShape
= pVmlDrawing
->getShapes().getShapeById( mxOleObjectInfo
->maShapeId
) )
2481 aGraphicPath
= pVmlShape
->getGraphicPath();
2483 // import and store the graphic
2484 if( !aGraphicPath
.isEmpty() )
2486 // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF)
2487 WmfExternal aExtHeader
;
2488 aExtHeader
.mapMode
= 8; // MM_ANISOTROPIC
2489 aExtHeader
.xExt
= rShapeRect
.Width
;
2490 aExtHeader
.yExt
= rShapeRect
.Height
;
2492 Reference
< graphic::XGraphic
> xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic( aGraphicPath
, &aExtHeader
);
2494 maShapeProperties
.setProperty(PROP_Graphic
, xGraphic
);
2501 return aServiceName
;
2504 void Shape::finalizeXShape( XmlFilterBase
& rFilter
, const Reference
< XShapes
>& rxShapes
)
2506 switch( meFrameType
)
2508 case FRAMETYPE_CHART
:
2510 OSL_ENSURE( !mxChartShapeInfo
->maFragmentPath
.isEmpty(), "Shape::finalizeXShape - missing chart fragment" );
2511 if( mxShape
.is() && !mxChartShapeInfo
->maFragmentPath
.isEmpty() ) try
2513 // set the chart2 OLE class ID at the OLE shape
2514 PropertySet
aShapeProp( mxShape
);
2515 aShapeProp
.setProperty( PROP_CLSID
, u
"12dcae26-281f-416f-a234-c3086127382e"_ustr
);
2517 // get the XModel interface of the embedded object from the OLE shape
2518 Reference
< frame::XModel
> xDocModel
;
2519 aShapeProp
.getProperty( xDocModel
, PROP_Model
);
2520 Reference
< chart2::XChartDocument
> xChartDoc( xDocModel
, UNO_QUERY_THROW
);
2522 // load the chart data from the XML fragment
2523 #if ENABLE_WASM_STRIP_CHART
2527 // WASM_CHART change
2528 // TODO: Instead of using convertFromModel an alternative may be
2529 // added to convert not to Chart/OLE SdrObejct, but to GraphicObject
2530 // with the Chart visualization. There should be a preview available
2531 // in the imported chart data
2532 bool bMSO2007Doc
= rFilter
.isMSO2007Document();
2533 chart::ChartSpaceModel
aModel(bMSO2007Doc
);
2534 oox::ppt::PowerPointImport
* pPowerPointImport
2535 = dynamic_cast<oox::ppt::PowerPointImport
*>(&rFilter
);
2537 ClrMapPtr pClrMap
; // The original color map
2538 if (pPowerPointImport
)
2540 // Use a copy of current color map, which the fragment may override locally
2541 pClrMap
= pPowerPointImport
->getActualSlidePersist()->getClrMap();
2542 aModel
.mpClrMap
= pClrMap
? std::make_shared
<ClrMap
>(*pClrMap
)
2543 : std::make_shared
<ClrMap
>();
2544 pPowerPointImport
->getActualSlidePersist()->setClrMap(aModel
.mpClrMap
);
2547 rtl::Reference
<chart::ChartSpaceFragment
> pChartSpaceFragment
= new chart::ChartSpaceFragment(
2548 rFilter
, mxChartShapeInfo
->maFragmentPath
, aModel
);
2549 const OUString
aThemeOverrideFragmentPath( pChartSpaceFragment
->
2550 getFragmentPathFromFirstTypeFromOfficeDoc(u
"themeOverride") );
2551 rFilter
.importFragment( pChartSpaceFragment
);
2553 // The original theme.
2556 if (!aThemeOverrideFragmentPath
.isEmpty() && pPowerPointImport
)
2558 // Handle theme override.
2559 uno::Reference
< xml::sax::XFastSAXSerializable
> xDoc(
2560 rFilter
.importFragment(aThemeOverrideFragmentPath
), uno::UNO_QUERY_THROW
);
2561 pTheme
= pPowerPointImport
->getActualSlidePersist()->getTheme();
2562 auto pThemeOverride
= std::make_shared
<Theme
>(*pTheme
);
2563 rFilter
.importFragment(
2564 new ThemeOverrideFragmentHandler(rFilter
, aThemeOverrideFragmentPath
, *pThemeOverride
, *pThemeOverride
->getTheme()),
2566 pPowerPointImport
->getActualSlidePersist()->setTheme(pThemeOverride
);
2569 // convert imported chart model to chart document
2570 Reference
< drawing::XShapes
> xExternalPage
;
2571 if( !mxChartShapeInfo
->mbEmbedShapes
)
2572 xExternalPage
= rxShapes
;
2573 if( rFilter
.getChartConverter() )
2575 rFilter
.getChartConverter()->convertFromModel( rFilter
, aModel
, xChartDoc
, xExternalPage
, mxShape
->getPosition(), mxShape
->getSize() );
2576 if( !xChartDoc
->hasInternalDataProvider() )
2578 Reference
< chart2::data::XDataReceiver
> xDataRec( xChartDoc
, UNO_QUERY
);
2579 Reference
< chart2::data::XDataSource
> xData
= xDataRec
->getUsedData();
2580 if( !xData
->getDataSequences().hasElements() || !xData
->getDataSequences()[0]->getValues().is() ||
2581 !xData
->getDataSequences()[0]->getValues()->getData().hasElements() )
2583 rFilter
.useInternalChartDataTable( true );
2584 rFilter
.getChartConverter()->convertFromModel( rFilter
, aModel
, xChartDoc
, xExternalPage
, mxShape
->getPosition(), mxShape
->getSize() );
2585 rFilter
.useInternalChartDataTable( false );
2591 if (pPowerPointImport
)
2593 if (!aThemeOverrideFragmentPath
.isEmpty())
2595 // Restore the original theme.
2596 pPowerPointImport
->getActualSlidePersist()->setTheme(pTheme
);
2598 // Restore the original color map
2599 pPowerPointImport
->getActualSlidePersist()->setClrMap(std::move(pClrMap
));
2613 void Shape::putPropertyToGrabBag( const OUString
& sPropertyName
, const Any
& aPropertyValue
)
2615 PropertyValue aNewProperty
;
2616 aNewProperty
.Name
= sPropertyName
;
2617 aNewProperty
.Value
= aPropertyValue
;
2618 putPropertyToGrabBag( aNewProperty
);
2621 void Shape::putPropertyToGrabBag( const PropertyValue
& pProperty
)
2623 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
2624 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
2625 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2626 if( mxShape
.is() && xSet
.is() && xSetInfo
.is() && xSetInfo
->hasPropertyByName( aGrabBagPropName
) )
2628 Sequence
< PropertyValue
> aGrabBag
;
2629 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2631 sal_Int32 length
= aGrabBag
.getLength();
2632 aGrabBag
.realloc( length
+ 1 );
2633 aGrabBag
.getArray()[length
] = pProperty
;
2635 xSet
->setPropertyValue( aGrabBagPropName
, Any( aGrabBag
) );
2639 void Shape::putPropertiesToGrabBag( const Sequence
< PropertyValue
>& aProperties
)
2641 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
2642 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
2643 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2644 if( !(mxShape
.is() && xSet
.is() && xSetInfo
.is() && xSetInfo
->hasPropertyByName( aGrabBagPropName
)) )
2647 // get existing grab bag
2648 Sequence
< PropertyValue
> aGrabBag
;
2649 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2651 std::vector
<PropertyValue
> aVec
;
2652 aVec
.reserve(aProperties
.getLength());
2654 // put the new items
2655 std::transform(aProperties
.begin(), aProperties
.end(), std::back_inserter(aVec
),
2656 [](const PropertyValue
& rProp
) {
2657 PropertyValue aProp
;
2658 aProp
.Name
= rProp
.Name
;
2659 aProp
.Value
= rProp
.Value
;
2663 // put it back to the shape
2664 xSet
->setPropertyValue( aGrabBagPropName
, Any( comphelper::concatSequences(aGrabBag
, aVec
) ) );
2667 FillProperties
Shape::getActualFillProperties(const Theme
* pTheme
, const FillProperties
* pParentShapeFillProps
) const
2669 FillProperties aFillProperties
;
2670 aFillProperties
.moFillType
= XML_noFill
;
2672 // Reference shape properties
2673 aFillProperties
.assignUsed( *mpShapeRefFillPropPtr
);
2676 if( pTheme
!= nullptr )
2678 if( const ShapeStyleRef
* pFillRef
= getShapeStyleRef( XML_fillRef
) )
2680 if( const FillProperties
* pFillProps
= pTheme
->getFillStyle( pFillRef
->mnThemedIdx
) )
2681 aFillProperties
.assignUsed( *pFillProps
);
2685 // Properties specified directly for this shape
2686 aFillProperties
.assignUsed(getFillProperties());
2688 // Parent shape's properties
2689 if ( pParentShapeFillProps
!= nullptr)
2690 if( getFillProperties().moFillType
.has_value() && getFillProperties().moFillType
.value() == XML_grpFill
)
2691 aFillProperties
.assignUsed( *pParentShapeFillProps
);
2693 return aFillProperties
;
2696 LineProperties
Shape::getActualLineProperties(const Theme
* pTheme
) const
2698 LineProperties aLineProperties
;
2699 aLineProperties
.maLineFill
.moFillType
= XML_noFill
;
2701 // Reference shape properties
2702 aLineProperties
.assignUsed( *mpShapeRefLinePropPtr
);
2705 if( pTheme
!= nullptr )
2707 if( const ShapeStyleRef
* pLineRef
= getShapeStyleRef( XML_lnRef
) )
2709 if( const LineProperties
* pLineProps
= pTheme
->getLineStyle( pLineRef
->mnThemedIdx
) )
2710 aLineProperties
.assignUsed( *pLineProps
);
2714 // Properties specified directly for this shape
2715 aLineProperties
.assignUsed( getLineProperties() );
2717 return aLineProperties
;
2720 EffectProperties
Shape::getActualEffectProperties(const Theme
* pTheme
) const
2722 EffectProperties aEffectProperties
;
2724 // Reference shape properties
2725 aEffectProperties
.assignUsed( *mpShapeRefEffectPropPtr
);
2728 if( pTheme
!= nullptr )
2730 if( const ShapeStyleRef
* pEffectRef
= getShapeStyleRef( XML_effectRef
) )
2732 if( const EffectProperties
* pEffectProps
= pTheme
->getEffectStyle( pEffectRef
->mnThemedIdx
) )
2733 aEffectProperties
.assignUsed( *pEffectProps
);
2737 // Properties specified directly for this shape
2738 aEffectProperties
.assignUsed ( getEffectProperties() );
2740 return aEffectProperties
;
2743 uno::Sequence
< uno::Sequence
< uno::Any
> > Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase
& rFilter
, const OUString
& sFragment
, std::u16string_view sType
)
2745 uno::Sequence
< uno::Sequence
< uno::Any
> > xRelListTemp
;
2746 sal_Int32 counter
= 0;
2748 core::RelationsRef xRels
= rFilter
.importRelations( sFragment
);
2751 core::RelationsRef xImageRels
= xRels
->getRelationsFromTypeFromOfficeDoc( sType
);
2754 xRelListTemp
.realloc( xImageRels
->size() );
2755 auto pxRelListTemp
= xRelListTemp
.getArray();
2756 for (auto const& imageRel
: *xImageRels
)
2758 uno::Sequence
< uno::Any
> diagramRelTuple (3);
2759 auto pdiagramRelTuple
= diagramRelTuple
.getArray();
2760 // [0] => RID, [1] => InputStream [2] => extension
2761 OUString sRelId
= imageRel
.second
.maId
;
2763 pdiagramRelTuple
[0] <<= sRelId
;
2764 OUString sTarget
= xImageRels
->getFragmentPathFromRelId( sRelId
);
2766 uno::Reference
< io::XInputStream
> xImageInputStrm( rFilter
.openInputStream( sTarget
), uno::UNO_SET_THROW
);
2767 StreamDataSequence dataSeq
;
2768 if ( rFilter
.importBinaryData( dataSeq
, sTarget
) )
2770 pdiagramRelTuple
[1] <<= dataSeq
;
2773 pdiagramRelTuple
[2] <<= sTarget
.copy( sTarget
.lastIndexOf(".") );
2775 pxRelListTemp
[counter
] = std::move(diagramRelTuple
);
2778 xRelListTemp
.realloc(counter
);
2782 return xRelListTemp
;
2785 void Shape::cloneFillProperties()
2787 auto pFillProperties
= std::make_shared
<FillProperties
>();
2788 pFillProperties
->assignUsed(*mpFillPropertiesPtr
);
2789 mpFillPropertiesPtr
= std::move(pFillProperties
);
2793 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */