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 "effectproperties.hxx"
32 #include <oox/drawingml/shapepropertymap.hxx>
33 #include <drawingml/textbody.hxx>
34 #include <drawingml/textparagraph.hxx>
35 #include <drawingml/ThemeOverrideFragmentHandler.hxx>
36 #include <drawingml/table/tableproperties.hxx>
37 #include <oox/drawingml/chart/chartconverter.hxx>
38 #include <drawingml/chart/chartspacefragment.hxx>
39 #include <drawingml/chart/chartspacemodel.hxx>
40 #include <o3tl/safeint.hxx>
41 #include <o3tl/unit_conversion.hxx>
42 #include <oox/ppt/pptimport.hxx>
43 #include <oox/vml/vmldrawing.hxx>
44 #include <oox/vml/vmlshape.hxx>
45 #include <oox/vml/vmlshapecontainer.hxx>
46 #include <oox/core/xmlfilterbase.hxx>
47 #include <oox/helper/graphichelper.hxx>
48 #include <oox/helper/propertyset.hxx>
49 #include <oox/helper/modelobjecthelper.hxx>
50 #include <oox/mathml/imexport.hxx>
51 #include <oox/mathml/importutils.hxx>
52 #include <oox/token/properties.hxx>
53 #include "diagram/datamodel.hxx"
54 #include "diagram/diagramhelper.hxx"
56 #include <comphelper/classids.hxx>
57 #include <comphelper/propertysequence.hxx>
58 #include <comphelper/propertyvalue.hxx>
59 #include <comphelper/sequence.hxx>
60 #include <comphelper/diagnose_ex.hxx>
61 #include <tools/gen.hxx>
62 #include <tools/globname.hxx>
63 #include <tools/mapunit.hxx>
64 #include <editeng/unoprnms.hxx>
65 #include <com/sun/star/awt/FontSlant.hpp>
66 #include <com/sun/star/awt/Size.hpp>
67 #include <com/sun/star/awt/XBitmap.hpp>
68 #include <com/sun/star/awt/FontWeight.hpp>
69 #include <com/sun/star/graphic/XGraphic.hpp>
70 #include <com/sun/star/container/XNamed.hpp>
71 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
72 #include <com/sun/star/xml/dom/XDocument.hpp>
73 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
74 #include <com/sun/star/drawing/FillStyle.hpp>
75 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
76 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
77 #include <com/sun/star/drawing/GraphicExportFilter.hpp>
78 #include <com/sun/star/drawing/XShapes.hpp>
79 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
80 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
81 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
82 #include <com/sun/star/drawing/ConnectorType.hpp>
83 #include <com/sun/star/embed/XEmbeddedObject.hpp>
84 #include <com/sun/star/text/XText.hpp>
85 #include <com/sun/star/table/BorderLine2.hpp>
86 #include <com/sun/star/table/ShadowFormat.hpp>
87 #include <com/sun/star/chart2/XChartDocument.hpp>
88 #include <com/sun/star/style/ParagraphAdjust.hpp>
89 #include <com/sun/star/io/XOutputStream.hpp>
90 #include <com/sun/star/lang/Locale.hpp>
91 #include <com/sun/star/i18n/ScriptType.hpp>
93 #include <basegfx/point/b2dpoint.hxx>
94 #include <basegfx/polygon/b2dpolygon.hxx>
95 #include <basegfx/matrix/b2dhommatrix.hxx>
96 #include <com/sun/star/document/XActionLockable.hpp>
97 #include <com/sun/star/chart2/data/XDataReceiver.hpp>
98 #include <com/sun/star/text/GraphicCrop.hpp>
99 #include <svx/svdobj.hxx>
100 #include <svx/svdotable.hxx>
101 #include <svx/svdtrans.hxx>
102 #include <tools/stream.hxx>
103 #include <unotools/streamwrap.hxx>
104 #include <unotools/fltrcfg.hxx>
105 #include <unotools/mediadescriptor.hxx>
106 #include <vcl/graph.hxx>
107 #include <vcl/graphicfilter.hxx>
108 #include <vcl/svapp.hxx>
109 #include <vcl/wmfexternal.hxx>
110 #include <sal/log.hxx>
111 #include <svx/sdtaitm.hxx>
112 #include <oox/drawingml/diagram/diagram.hxx>
113 #include <docmodel/theme/Theme.hxx>
114 #include <i18nlangtag/languagetag.hxx>
115 #include <i18nlangtag/mslangid.hxx>
117 using namespace ::oox::core
;
118 using namespace ::com::sun::star
;
119 using namespace ::com::sun::star::uno
;
120 using namespace ::com::sun::star::beans
;
121 using namespace ::com::sun::star::frame
;
122 using namespace ::com::sun::star::text
;
123 using namespace ::com::sun::star::drawing
;
124 using namespace ::com::sun::star::style
;
126 namespace oox::drawingml
{
128 Shape::Shape( const char* pServiceName
, bool bDefaultHeight
)
129 : mpLinePropertiesPtr( std::make_shared
<LineProperties
>() )
130 , mpShapeRefLinePropPtr( std::make_shared
<LineProperties
>() )
131 , mpFillPropertiesPtr( std::make_shared
<FillProperties
>() )
132 , mpShapeRefFillPropPtr( std::make_shared
<FillProperties
>() )
133 , mpGraphicPropertiesPtr( std::make_shared
<GraphicProperties
>() )
134 , mpCustomShapePropertiesPtr( std::make_shared
<CustomShapeProperties
>() )
135 , mp3DPropertiesPtr( std::make_shared
<Shape3DProperties
>() )
136 , mpEffectPropertiesPtr( std::make_shared
<EffectProperties
>() )
137 , mpShapeRefEffectPropPtr( std::make_shared
<EffectProperties
>() )
138 , mpMasterTextListStyle( std::make_shared
<TextListStyle
>() )
140 , meFrameType( FRAMETYPE_GENERIC
)
142 , mnDiagramRotation( 0 )
146 , mbHiddenMasterShape( false )
149 , mbLockedCanvas( false )
152 , mbHasLinkedTxbx( false )
154 , mpDiagramHelper( nullptr )
157 msServiceName
= OUString::createFromAscii( pServiceName
);
158 setDefaults(bDefaultHeight
);
161 Shape::Shape( const ShapePtr
& pSourceShape
)
162 : mpTextBody(pSourceShape
->mpTextBody
)
163 , mpLinePropertiesPtr( pSourceShape
->mpLinePropertiesPtr
)
164 , mpShapeRefLinePropPtr( pSourceShape
->mpShapeRefLinePropPtr
)
165 , mpFillPropertiesPtr( pSourceShape
->mpFillPropertiesPtr
)
166 , mpShapeRefFillPropPtr( pSourceShape
->mpShapeRefFillPropPtr
)
167 , mpGraphicPropertiesPtr( pSourceShape
->mpGraphicPropertiesPtr
)
168 , mpCustomShapePropertiesPtr( pSourceShape
->mpCustomShapePropertiesPtr
)
169 , mpTablePropertiesPtr( pSourceShape
->mpTablePropertiesPtr
)
170 , mp3DPropertiesPtr( pSourceShape
->mp3DPropertiesPtr
)
171 , mpEffectPropertiesPtr (pSourceShape
->mpEffectPropertiesPtr
)
172 , mpShapeRefEffectPropPtr(pSourceShape
->mpShapeRefEffectPropPtr
)
173 , maShapeProperties( pSourceShape
->maShapeProperties
)
174 , mpMasterTextListStyle( pSourceShape
->mpMasterTextListStyle
)
175 , msServiceName( pSourceShape
->msServiceName
)
176 , msName( pSourceShape
->msName
)
177 , msInternalName( pSourceShape
->msInternalName
)
178 , msId( pSourceShape
->msId
)
179 , mnSubType( pSourceShape
->mnSubType
)
180 , moSubTypeIndex( pSourceShape
->moSubTypeIndex
)
181 , maShapeStyleRefs( pSourceShape
->maShapeStyleRefs
)
182 , maSize( pSourceShape
->maSize
)
183 , maPosition( pSourceShape
->maPosition
)
184 , meFrameType( pSourceShape
->meFrameType
)
185 , mnRotation( pSourceShape
->mnRotation
)
186 , mnDiagramRotation( pSourceShape
->mnDiagramRotation
)
187 , mbFlipH( pSourceShape
->mbFlipH
)
188 , mbFlipV( pSourceShape
->mbFlipV
)
189 , mbHidden( pSourceShape
->mbHidden
)
190 , mbHiddenMasterShape( pSourceShape
->mbHiddenMasterShape
)
191 , mbLocked( pSourceShape
->mbLocked
)
192 , mbWPGChild( pSourceShape
->mbWPGChild
)
193 , mbLockedCanvas( pSourceShape
->mbLockedCanvas
)
194 , mbWps( pSourceShape
->mbWps
)
195 , mbTextBox( pSourceShape
->mbTextBox
)
196 , mbHasLinkedTxbx(false)
197 , maDiagramDoms( pSourceShape
->maDiagramDoms
)
198 , mnZOrder(pSourceShape
->mnZOrder
)
199 , mnZOrderOff(pSourceShape
->mnZOrderOff
)
200 , mnDataNodeType(pSourceShape
->mnDataNodeType
)
201 , mfAspectRatio(pSourceShape
->mfAspectRatio
)
202 , mpDiagramHelper( nullptr )
203 , msDiagramDataModelID(pSourceShape
->msDiagramDataModelID
)
208 // DiagramHelper should not be set here anymore, see
209 // propagateDiagramHelper below (maybe assert..?)
210 delete mpDiagramHelper
;
213 void Shape::prepareDiagramHelper(
214 const std::shared_ptr
< Diagram
>& rDiagramPtr
,
215 const std::shared_ptr
<::oox::drawingml::Theme
>& rTheme
)
217 // Prepare Diagram data collecting for this Shape
218 if( nullptr == mpDiagramHelper
&& FRAMETYPE_DIAGRAM
== meFrameType
)
220 mpDiagramHelper
= new AdvancedDiagramHelper(
227 void Shape::propagateDiagramHelper()
229 // Propagate collected Diagram data to data holder
230 if (FRAMETYPE_DIAGRAM
== meFrameType
&& nullptr != mpDiagramHelper
)
232 SdrObjGroup
* pAnchorObj
= dynamic_cast<SdrObjGroup
*>(SdrObject::getSdrObjectFromXShape(mxShape
));
236 static_cast<AdvancedDiagramHelper
*>(mpDiagramHelper
)->doAnchor(*pAnchorObj
, *this);
237 mpDiagramHelper
= nullptr;
241 // If propagation failed, delete/cleanup here. Since the DiagramHelper
242 // holds a Diagram and that this Shape it is necessary - the destructor
243 // will not be called and will be too late
244 if (nullptr != mpDiagramHelper
)
246 delete mpDiagramHelper
;
247 mpDiagramHelper
= nullptr;
251 void Shape::migrateDiagramHelperToNewShape(const ShapePtr
& pTarget
)
260 // no migrate target, but cleanup helper
261 delete mpDiagramHelper
;
262 mpDiagramHelper
= nullptr;
266 if(pTarget
->mpDiagramHelper
)
268 // this should no happen, but if there is already a helper, clean it up
269 delete pTarget
->mpDiagramHelper
;
270 pTarget
->mpDiagramHelper
= nullptr;
273 // exchange and reset to nullptr
274 pTarget
->mpDiagramHelper
= mpDiagramHelper
;
275 mpDiagramHelper
= nullptr;
278 table::TablePropertiesPtr
const & Shape::getTableProperties()
280 if ( !mpTablePropertiesPtr
)
281 mpTablePropertiesPtr
= std::make_shared
<table::TableProperties
>();
282 return mpTablePropertiesPtr
;
285 void Shape::setDefaults(bool bHeight
)
287 maDefaultShapeProperties
.setProperty(PROP_TextAutoGrowHeight
, false);
288 maDefaultShapeProperties
.setProperty(PROP_TextWordWrap
, true);
289 maDefaultShapeProperties
.setProperty(PROP_TextLeftDistance
, static_cast< sal_Int32
>( 250 ));
290 maDefaultShapeProperties
.setProperty(PROP_TextUpperDistance
, static_cast< sal_Int32
>( 125 ));
291 maDefaultShapeProperties
.setProperty(PROP_TextRightDistance
, static_cast< sal_Int32
>( 250 ));
292 maDefaultShapeProperties
.setProperty(PROP_TextLowerDistance
, static_cast< sal_Int32
>( 125 ));
294 maDefaultShapeProperties
.setProperty(PROP_CharHeight
, static_cast< float >( 18.0 ));
295 maDefaultShapeProperties
.setProperty(PROP_TextVerticalAdjust
, TextVerticalAdjust_TOP
);
296 maDefaultShapeProperties
.setProperty(PROP_ParaAdjust
,
297 static_cast<sal_Int16
>(ParagraphAdjust_LEFT
));
300 ::oox::vml::OleObjectInfo
& Shape::setOleObjectType()
302 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setOleObjectType - multiple frame types" );
303 meFrameType
= FRAMETYPE_OLEOBJECT
;
304 mxOleObjectInfo
= std::make_shared
<::oox::vml::OleObjectInfo
>( true );
305 return *mxOleObjectInfo
;
308 ChartShapeInfo
& Shape::setChartType( bool bEmbedShapes
)
310 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setChartType - multiple frame types" );
311 meFrameType
= FRAMETYPE_CHART
;
313 msServiceName
= "com.sun.star.drawing.temporaryForXMLImportOLE2Shape";
315 msServiceName
= "com.sun.star.drawing.OLE2Shape";
316 mxChartShapeInfo
= std::make_shared
<ChartShapeInfo
>( bEmbedShapes
);
317 return *mxChartShapeInfo
;
320 void Shape::setDiagramType()
322 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setDiagramType - multiple frame types" );
323 meFrameType
= FRAMETYPE_DIAGRAM
;
324 msServiceName
= "com.sun.star.drawing.GroupShape";
328 void Shape::setTableType()
330 OSL_ENSURE( meFrameType
== FRAMETYPE_GENERIC
, "Shape::setTableType - multiple frame types" );
331 meFrameType
= FRAMETYPE_TABLE
;
332 msServiceName
= "com.sun.star.drawing.TableShape";
336 void Shape::setServiceName( const char* pServiceName
)
339 msServiceName
= OUString::createFromAscii( pServiceName
);
342 const ShapeStyleRef
* Shape::getShapeStyleRef( sal_Int32 nRefType
) const
344 ShapeStyleRefMap::const_iterator aIt
= maShapeStyleRefs
.find( nRefType
);
345 return (aIt
== maShapeStyleRefs
.end()) ? nullptr : &aIt
->second
;
348 void Shape::addShape(
349 ::oox::core::XmlFilterBase
& rFilterBase
,
351 const Reference
< XShapes
>& rxShapes
,
352 const basegfx::B2DHomMatrix
& aTransformation
,
353 const FillProperties
& rShapeOrParentShapeFillProps
,
354 ShapeIdMap
* pShapeMap
,
355 oox::drawingml::ShapePtr pParentGroupShape
)
357 SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId
<< "'");
361 OUString
sServiceName( msServiceName
);
362 if( !sServiceName
.isEmpty() )
364 basegfx::B2DHomMatrix
aMatrix( aTransformation
);
365 Reference
< XShape
> xShape( createAndInsert( rFilterBase
, sServiceName
, pTheme
, rxShapes
, false, false, aMatrix
, rShapeOrParentShapeFillProps
, pParentGroupShape
) );
367 if( pShapeMap
&& !msId
.isEmpty() )
369 (*pShapeMap
)[ msId
] = shared_from_this();
372 // if this is a group shape, we have to add also each child shape
373 Reference
< XShapes
> xShapes( xShape
, UNO_QUERY
);
375 addChildren( rFilterBase
, *this, pTheme
, xShapes
, pShapeMap
, aMatrix
);
377 if (isWPGChild() && xShape
)
379 // This is a wps shape and it is the child of the WPG, now copy the
380 // the text body properties to the xshape.
381 Reference
<XPropertySet
> xChildWPSProperties(xShape
, uno::UNO_QUERY
);
383 if (getTextBody() && xChildWPSProperties
)
385 xChildWPSProperties
->setPropertyValue(
386 UNO_NAME_TEXT_VERTADJUST
,
387 uno::Any(getTextBody()->getTextProperties().meVA
));
389 xChildWPSProperties
->setPropertyValue(
390 UNO_NAME_TEXT_LEFTDIST
,
391 uno::Any(getTextBody()->getTextProperties().moInsets
[0].has_value()
392 ? *getTextBody()->getTextProperties().moInsets
[0]
394 xChildWPSProperties
->setPropertyValue(
395 UNO_NAME_TEXT_UPPERDIST
,
396 uno::Any(getTextBody()->getTextProperties().moInsets
[1].has_value()
397 ? *getTextBody()->getTextProperties().moInsets
[1]
399 xChildWPSProperties
->setPropertyValue(
400 UNO_NAME_TEXT_RIGHTDIST
,
401 uno::Any(getTextBody()->getTextProperties().moInsets
[2].has_value()
402 ? *getTextBody()->getTextProperties().moInsets
[2]
404 xChildWPSProperties
->setPropertyValue(
405 UNO_NAME_TEXT_LOWERDIST
,
406 uno::Any(getTextBody()->getTextProperties().moInsets
[3].has_value()
407 ? *getTextBody()->getTextProperties().moInsets
[3]
411 // tdf#145147 Set the Hyperlink property to the child wps shape.
412 if (getShapeProperties().hasProperty(PROP_URL
)) try
414 uno::Any aAny
= getShapeProperties().getProperty(PROP_URL
);
415 OUString sUrl
= aAny
.get
<OUString
>();
417 xChildWPSProperties
->setPropertyValue(UNO_NAME_HYPERLINK
, aAny
);
419 catch (const Exception
&)
424 if( meFrameType
== FRAMETYPE_DIAGRAM
)
426 keepDiagramCompatibilityInfo();
428 // set DiagramHelper at SdrObjGroup
429 propagateDiagramHelper();
431 // Check if this is the PPTX import, so far converting SmartArt to a non-editable
432 // metafile is only implemented for DOCX.
433 bool bPowerPoint
= dynamic_cast<oox::ppt::PowerPointImport
*>(&rFilterBase
) != nullptr;
435 if (!SvtFilterOptions::Get().IsSmartArt2Shape() && !bPowerPoint
)
436 convertSmartArtToMetafile( rFilterBase
);
439 NamedShapePairs
* pNamedShapePairs
= rFilterBase
.getDiagramFontHeights();
440 if (xShape
.is() && pNamedShapePairs
)
442 auto itPairs
= pNamedShapePairs
->find(getInternalName());
443 if (itPairs
!= pNamedShapePairs
->end())
445 auto it
= itPairs
->second
.find(shared_from_this());
446 if (it
!= itPairs
->second
.end())
448 // Our drawingml::Shape is in the list of an internal name, remember the now
456 catch( const Exception
& )
458 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" );
462 void Shape::setLockedCanvas(bool bLockedCanvas
)
464 mbLockedCanvas
= bLockedCanvas
;
467 void Shape::setWPGChild(bool bWPG
)
472 void Shape::setWps(bool bWps
)
477 void Shape::setTextBox(bool bTextBox
)
479 mbTextBox
= bTextBox
;
482 void Shape::applyShapeReference( const Shape
& rReferencedShape
, bool bUseText
)
484 SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape
.msId
<< "' to '" << msId
<< "'");
486 if ( rReferencedShape
.mpTextBody
&& bUseText
)
487 mpTextBody
= std::make_shared
<TextBody
>( *rReferencedShape
.mpTextBody
);
490 maShapeProperties
= rReferencedShape
.maShapeProperties
;
491 mpShapeRefLinePropPtr
= std::make_shared
<LineProperties
>( rReferencedShape
.getActualLineProperties(nullptr) );
492 mpShapeRefFillPropPtr
= std::make_shared
<FillProperties
>( rReferencedShape
.getActualFillProperties(nullptr, nullptr) );
493 mpCustomShapePropertiesPtr
= std::make_shared
<CustomShapeProperties
>( *rReferencedShape
.mpCustomShapePropertiesPtr
);
494 mpTablePropertiesPtr
= rReferencedShape
.mpTablePropertiesPtr
? std::make_shared
<table::TableProperties
>( *rReferencedShape
.mpTablePropertiesPtr
) : nullptr;
495 mpShapeRefEffectPropPtr
= std::make_shared
<EffectProperties
>( rReferencedShape
.getActualEffectProperties(nullptr) );
496 mpMasterTextListStyle
= std::make_shared
<TextListStyle
>( *rReferencedShape
.mpMasterTextListStyle
);
497 maSize
= rReferencedShape
.maSize
;
498 maPosition
= rReferencedShape
.maPosition
;
499 mnRotation
= rReferencedShape
.mnRotation
;
500 mbFlipH
= rReferencedShape
.mbFlipH
;
501 mbFlipV
= rReferencedShape
.mbFlipV
;
502 mbHidden
= rReferencedShape
.mbHidden
;
503 mbLocked
= rReferencedShape
.mbLocked
;
508 struct ActionLockGuard
510 explicit ActionLockGuard(Reference
<drawing::XShape
> const& xShape
)
511 : m_xLockable(xShape
, UNO_QUERY
)
513 if (m_xLockable
.is()) {
514 m_xLockable
->addActionLock();
519 if (m_xLockable
.is()) {
520 m_xLockable
->removeActionLock();
524 Reference
<document::XActionLockable
> m_xLockable
;
529 // for group shapes, the following method is also adding each child
530 void Shape::addChildren(
531 XmlFilterBase
& rFilterBase
,
534 const Reference
< XShapes
>& rxShapes
,
535 ShapeIdMap
* pShapeMap
,
536 const basegfx::B2DHomMatrix
& aTransformation
)
538 for (auto const& child
: rMaster
.maChildren
)
540 child
->setMasterTextListStyle( mpMasterTextListStyle
);
541 child
->addShape( rFilterBase
, pTheme
, rxShapes
, aTransformation
, getFillProperties(), pShapeMap
, rMaster
.shared_from_this());
545 static SdrTextHorzAdjust
lcl_convertAdjust( ParagraphAdjust eAdjust
)
547 if (eAdjust
== ParagraphAdjust_LEFT
)
548 return SDRTEXTHORZADJUST_LEFT
;
549 else if (eAdjust
== ParagraphAdjust_RIGHT
)
550 return SDRTEXTHORZADJUST_RIGHT
;
551 else if (eAdjust
== ParagraphAdjust_CENTER
)
552 return SDRTEXTHORZADJUST_CENTER
;
553 return SDRTEXTHORZADJUST_LEFT
;
556 // LO does not interpret properties in styles belonging to the text content of a FontWork shape,
557 // but only those in the shape style. This method copies properties from the text content styles to
559 static void lcl_copyCharPropsToShape(const uno::Reference
<drawing::XShape
>& xShape
,
560 const TextBodyPtr
& pTextBody
,
561 const ::oox::core::XmlFilterBase
& rFilter
)
563 if (!xShape
.is() || !pTextBody
)
566 Reference
<XPropertySet
> xSet(xShape
, UNO_QUERY
);
570 // Content stretches or scales to given width and height, thus disable autogrow.
571 xSet
->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT
, uno::Any(false));
572 xSet
->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH
, uno::Any(false));
574 // LibreOffice is not able (as of Nov 2022) to use different styles for the paragraphs or
575 // characters in FontWork, since that was not allowed in old binary WordArt. We use the
576 // properties of the first non empty paragraph for now.
577 const TextParagraphVector
& rParagraphs
= pTextBody
->getParagraphs();
578 auto aParaIt
= std::find_if_not(rParagraphs
.cbegin(), rParagraphs
.cend(),
579 [](const std::shared_ptr
<TextParagraph
> pParagraph
) {
580 return pParagraph
->getRuns().empty();
582 if (aParaIt
!= rParagraphs
.cend())
584 std::shared_ptr
<TextParagraph
> pParagraph
= *aParaIt
;
585 const TextRunVector
& rRuns
= pParagraph
->getRuns();
586 auto aRunIt
= std::find_if_not(
587 rRuns
.cbegin(), rRuns
.cend(),
588 [](const std::shared_ptr
<TextRun
> pRun
) { return pRun
->getText().isEmpty(); });
589 if (aRunIt
!= rRuns
.cend())
591 std::shared_ptr
<TextRun
> pRun
= *aRunIt
;
592 TextCharacterProperties
& rCharProps
= pRun
->getTextCharacterProperties();
595 if (rCharProps
.moLang
.has_value() && !rCharProps
.moLang
.value().isEmpty())
597 LanguageTag
aTag(rCharProps
.moLang
.value());
598 css::lang::Locale
aLocale(aTag
.getLocale(false));
599 switch (MsLangId::getScriptType(aTag
.getLanguageType()))
601 case css::i18n::ScriptType::LATIN
:
602 xSet
->setPropertyValue(u
"CharLocale", uno::Any(aLocale
));
604 case css::i18n::ScriptType::ASIAN
:
605 xSet
->setPropertyValue(u
"CharLocaleAsian", uno::Any(aLocale
));
607 case css::i18n::ScriptType::COMPLEX
:
608 xSet
->setPropertyValue(u
"CharLocaleComplex", uno::Any(aLocale
));
614 // Font Weight, Posture, Height
615 if (rCharProps
.moBold
.has_value() && rCharProps
.moBold
.value())
617 xSet
->setPropertyValue(UNO_NAME_CHAR_WEIGHT
, uno::Any(css::awt::FontWeight::BOLD
));
619 if (rCharProps
.moItalic
.has_value() && rCharProps
.moItalic
.value())
621 xSet
->setPropertyValue(UNO_NAME_CHAR_POSTURE
,
622 uno::Any(css::awt::FontSlant::FontSlant_ITALIC
));
624 if (rCharProps
.moHeight
.has_value())
626 sal_Int32 nHeight
= rCharProps
.moHeight
.value() / 100;
627 xSet
->setPropertyValue(UNO_NAME_CHAR_HEIGHT
, uno::Any(nHeight
));
630 // Put theme fonts into shape properties
632 sal_Int16 nFontPitch
= 0;
633 sal_Int16 nFontFamily
= 0;
635 if (const Theme
* pTheme
= rFilter
.getCurrentTheme())
638 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-lt"))
640 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
643 xSet
->setPropertyValue(u
"CharFontName", uno::Any(sFontName
));
644 xSet
->setPropertyValue(u
"CharFontPitch", uno::Any(nFontPitch
));
645 xSet
->setPropertyValue(u
"CharFontFamily", uno::Any(nFontFamily
));
649 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-ea"))
651 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
654 xSet
->setPropertyValue(u
"CharFontNameAsian", uno::Any(sFontName
));
655 xSet
->setPropertyValue(u
"CharFontPitchAsian", uno::Any(nFontPitch
));
656 xSet
->setPropertyValue(u
"CharFontFamilyAsian", uno::Any(nFontFamily
));
660 if (const TextFont
* pFont
= pTheme
->resolveFont(u
"+mn-cs"))
662 bRet
= pFont
->getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
665 xSet
->setPropertyValue(u
"CharFontNameComplex", uno::Any(sFontName
));
666 xSet
->setPropertyValue(u
"CharFontPitchComplex", uno::Any(nFontPitch
));
667 xSet
->setPropertyValue(u
"CharFontFamilyComplex", uno::Any(nFontFamily
));
672 // Replace theme fonts with formatting at run if any. ToDo: Inspect paragraph too?
674 bRet
= rCharProps
.maLatinFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
676 // In case there is no direct font, try to look it up as a theme reference.
677 bRet
= rCharProps
.maLatinThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
,
682 xSet
->setPropertyValue(u
"CharFontName", uno::Any(sFontName
));
683 xSet
->setPropertyValue(u
"CharFontPitch", uno::Any(nFontPitch
));
684 xSet
->setPropertyValue(u
"CharFontFamily", uno::Any(nFontFamily
));
687 bRet
= rCharProps
.maAsianFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
689 // In case there is no direct font, try to look it up as a theme reference.
690 bRet
= rCharProps
.maAsianThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
,
694 xSet
->setPropertyValue(u
"CharFontNameAsian", uno::Any(sFontName
));
695 xSet
->setPropertyValue(u
"CharFontPitchAsian", uno::Any(nFontPitch
));
696 xSet
->setPropertyValue(u
"CharFontFamilyAsian", uno::Any(nFontFamily
));
700 = rCharProps
.maComplexFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
, rFilter
);
702 // In case there is no direct font, try to look it up as a theme reference.
703 bRet
= rCharProps
.maComplexThemeFont
.getFontData(sFontName
, nFontPitch
, nFontFamily
,
707 xSet
->setPropertyValue(u
"CharFontNameComplex", uno::Any(sFontName
));
708 xSet
->setPropertyValue(u
"CharFontPitchComplex", uno::Any(nFontPitch
));
709 xSet
->setPropertyValue(u
"CharFontFamilyComplex", uno::Any(nFontFamily
));
712 // LO uses shape properties, MS Office character properties. Copy them from char to shape.
714 if (rCharProps
.moTextOutlineProperties
.has_value())
716 oox::drawingml::ShapePropertyMap
aStrokeShapeProps(rFilter
.getModelObjectHelper());
717 rCharProps
.moTextOutlineProperties
.value().pushToPropMap(
718 aStrokeShapeProps
, rFilter
.getGraphicHelper());
719 for (const auto& rProp
: aStrokeShapeProps
.makePropertyValueSequence())
721 xSet
->setPropertyValue(rProp
.Name
, rProp
.Value
);
726 xSet
->setPropertyValue(UNO_NAME_LINESTYLE
, uno::Any(drawing::LineStyle_NONE
));
730 // ToDo: Replace flip and rotate constants in parameters with actual values.
731 // tdf#155327 If color is not explicitly set, MS Office uses scheme color 'tx1'.
732 oox::drawingml::ShapePropertyMap
aFillShapeProps(rFilter
.getModelObjectHelper());
733 if (!rCharProps
.maFillProperties
.moFillType
.has_value())
734 rCharProps
.maFillProperties
.moFillType
= XML_solidFill
;
735 if (!rCharProps
.maFillProperties
.maFillColor
.isUsed())
736 rCharProps
.maFillProperties
.maFillColor
.setSchemeClr(XML_tx1
);
737 rCharProps
.maFillProperties
.pushToPropMap(aFillShapeProps
, rFilter
.getGraphicHelper(),
738 /*nShapeRotation*/ 0,
739 /*nPhClr*/ API_RGB_TRANSPARENT
,
740 /*aShapeSize*/ css::awt::Size(0, 0),
742 /*bFlipH*/ false, /*bFlipV*/ false,
743 /*bIsCustomShape*/ true);
744 for (const auto& rProp
: aFillShapeProps
.makePropertyValueSequence())
746 xSet
->setPropertyValue(rProp
.Name
, rProp
.Value
);
749 // ToDo: Import WordArt glow and simple shadow effects. They are available in LO.
752 // LO does not evaluate paragraph alignment in text path mode. Use text area anchor instead.
754 ParagraphAdjust eAdjust
= ParagraphAdjust_LEFT
;
755 if (pParagraph
->getProperties().getParaAdjust())
756 eAdjust
= *pParagraph
->getProperties().getParaAdjust();
757 xSet
->setPropertyValue("ParaAdjust", uno::Any(eAdjust
));
758 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(xShape
);
760 SdrTextHorzAdjust eHorzAdjust
= lcl_convertAdjust(eAdjust
);
761 pShape
->SetMergedItem(SdrTextHorzAdjustItem(eHorzAdjust
));
765 // Vertical adjustment is only meaningful for OOXML WordArt shapes of 'Follow Path' kinds. We set
766 // it so, that text position is approximately same as in MS Office.
767 const OUString sMSPresetType
= pTextBody
->getTextProperties().msPrst
;
768 const OUString sFontworkType
= PresetGeometryTypeNames::GetFontworkType(sMSPresetType
);
769 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(xShape
);
771 if (sFontworkType
== "fontwork-arch-up-curve" || sFontworkType
== "fontwork-circle-curve")
772 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM
));
773 else if (sFontworkType
== "fontwork-arch-down-curve")
774 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP
));
776 pShape
->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_CENTER
));
779 // Some helper methods for createAndInsert
782 // mirrors aTransformation at its center axis
783 // only valid if neither rotation or shear included
784 void lcl_mirrorAtCenter(basegfx::B2DHomMatrix
& aTransformation
, bool bFlipH
, bool bFlipV
)
786 if (!bFlipH
&& !bFlipV
)
788 basegfx::B2DPoint
aCenter(0.5, 0.5);
789 aCenter
*= aTransformation
;
790 aTransformation
.translate(-aCenter
);
791 aTransformation
.scale(bFlipH
? -1.0 : 1.0, bFlipV
? -1.0 : 1.0);
792 aTransformation
.translate(aCenter
);
796 // only valid if neither rotation or shear included
797 void lcl_doSpecialMSOWidthHeightToggle(basegfx::B2DHomMatrix
& aTransformation
)
799 // The values are directly set at the matrix without any matrix multiplication.
800 // That way it is valid for lines too. Those have zero width or height.
801 const double fSx(aTransformation
.get(0, 0));
802 const double fSy(aTransformation
.get(1, 1));
803 const double fTx(aTransformation
.get(0, 2));
804 const double fTy(aTransformation
.get(1, 2));
805 aTransformation
.set(0, 0, fSy
);
806 aTransformation
.set(1, 1, fSx
);
807 aTransformation
.set(0, 2, fTx
+ 0.5 * (fSx
- fSy
));
808 aTransformation
.set(1, 2, fTy
+ 0.5 * (fSy
- fSx
));
812 void lcl_RotateAtCenter(basegfx::B2DHomMatrix
& aTransformation
,sal_Int32 nMSORotationAngle
)
814 if (nMSORotationAngle
== 0)
816 double fRad
= basegfx::deg2rad
<60000>(nMSORotationAngle
);
817 basegfx::B2DPoint
aCenter(0.5, 0.5);
818 aCenter
*= aTransformation
;
819 aTransformation
.translate(-aCenter
);
820 aTransformation
.rotate(fRad
);
821 aTransformation
.translate(aCenter
);
826 Reference
< XShape
> const & Shape::createAndInsert(
827 ::oox::core::XmlFilterBase
& rFilterBase
,
828 const OUString
& rServiceName
,
830 const css::uno::Reference
< css::drawing::XShapes
>& rxShapes
,
832 bool bDoNotInsertEmptyTextBody
,
833 basegfx::B2DHomMatrix
& aParentTransformation
,
834 const FillProperties
& rShapeOrParentShapeFillProps
,
835 oox::drawingml::ShapePtr pParentGroupShape
)
837 bool bIsEmbMedia
= false;
838 SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId
<< "' service='" << rServiceName
<< "'");
840 formulaimport::XmlStreamBuilder
* pMathXml(nullptr);
843 for (auto const& it
: mpTextBody
->getParagraphs())
845 if (it
->HasMathXml())
847 if (!mpTextBody
->isEmpty() || pMathXml
!= nullptr)
849 SAL_WARN("oox.drawingml", "losing a Math object...");
853 pMathXml
= &it
->GetMathXml();
859 // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height
860 if ( mpTablePropertiesPtr
&& rServiceName
== "com.sun.star.drawing.TableShape" )
863 for (auto const& elem
: mpTablePropertiesPtr
->getTableGrid())
865 maSize
.Width
= o3tl::saturating_add(maSize
.Width
, static_cast<sal_Int32
>(elem
));
868 for (auto const& elem
: mpTablePropertiesPtr
->getTableRows())
870 // WARN: If some rows can't fit the content, this is not the final height
871 maSize
.Height
= o3tl::saturating_add(maSize
.Height
, elem
.getHeight());
875 awt::Rectangle
aShapeRectHmm(
876 o3tl::convert(maPosition
.X
, o3tl::Length::emu
, o3tl::Length::mm100
),
877 o3tl::convert(maPosition
.Y
, o3tl::Length::emu
, o3tl::Length::mm100
),
878 o3tl::convert(maSize
.Width
, o3tl::Length::emu
, o3tl::Length::mm100
),
879 o3tl::convert(maSize
.Height
, o3tl::Length::emu
, o3tl::Length::mm100
));
881 OUString aServiceName
;
884 // convert this shape to OLE
885 aServiceName
= "com.sun.star.drawing.OLE2Shape";
886 msServiceName
= aServiceName
;
887 meFrameType
= FRAMETYPE_GENERIC
; // not OLEOBJECT, no stream in package
890 else if (rServiceName
== "com.sun.star.drawing.GraphicObjectShape" &&
891 mpGraphicPropertiesPtr
&& !mpGraphicPropertiesPtr
->m_sMediaPackageURL
.isEmpty())
893 aServiceName
= finalizeServiceName( rFilterBase
, "com.sun.star.presentation.MediaShape", aShapeRectHmm
);
898 aServiceName
= finalizeServiceName( rFilterBase
, rServiceName
, aShapeRectHmm
);
900 // Use custom shape instead of GraphicObjectShape if the image is cropped to
901 // shape. Except rectangle, which does not require further cropping
902 bool bIsCroppedGraphic
= (aServiceName
== "com.sun.star.drawing.GraphicObjectShape" &&
903 !mpCustomShapePropertiesPtr
->representsDefaultShape());
905 bool bIsCustomShape
= (aServiceName
== "com.sun.star.drawing.CustomShape" || bIsCroppedGraphic
);
906 bool bIsConnectorShape
= (aServiceName
== "com.sun.star.drawing.ConnectorShape");
907 if(bIsCroppedGraphic
)
909 aServiceName
= "com.sun.star.drawing.CustomShape";
910 mpGraphicPropertiesPtr
->mbIsCustomShape
= true;
912 bool bUseRotationTransform
= ( !mbWps
||
913 aServiceName
== "com.sun.star.drawing.LineShape" ||
914 aServiceName
== "com.sun.star.drawing.GroupShape" ||
918 basegfx::B2DHomMatrix aTransformation
; // will be cumulative transformation of this object
920 // Special for SmartArt import. Rotate diagram's shape around object's center before sizing.
921 if (bUseRotationTransform
&& mnDiagramRotation
!= 0)
923 aTransformation
.translate(-0.5, -0.5);
924 aTransformation
.rotate(basegfx::deg2rad
<60000>(mnDiagramRotation
));
925 aTransformation
.translate(0.5, 0.5);
928 // Build object matrix from shape size and position; corresponds to MSO ext and off
929 // Only LineShape and ConnectorShape may have zero width or height.
930 if (aServiceName
== "com.sun.star.drawing.LineShape"
931 || aServiceName
== "com.sun.star.drawing.ConnectorShape")
932 aTransformation
.scale(maSize
.Width
, maSize
.Height
);
935 aTransformation
.scale(maSize
.Width
? maSize
.Width
: 1.0,
936 maSize
.Height
? maSize
.Height
: 1.0);
939 // Evaluate object flip. Other shapes than custom shapes have no attribute for flip but use
940 // negative scale. Flip in MSO is at object center.
941 if (!bIsCustomShape
&& (mbFlipH
|| mbFlipV
))
942 lcl_mirrorAtCenter(aTransformation
, mbFlipH
, mbFlipV
);
944 // Evaluate parent flip.
945 // A CustomShape has mirror not as negative scale, but as attributes.
946 basegfx::B2DVector
aParentScale(1.0, 1.0);
947 basegfx::B2DVector
aParentTranslate(0.0, 0.0);
948 double fParentRotate(0.0);
949 double fParentShearX(0.0);
950 if (pParentGroupShape
)
952 aParentTransformation
.decompose(aParentScale
, aParentTranslate
, fParentRotate
, fParentShearX
);
955 lcl_mirrorAtCenter(aTransformation
, aParentScale
.getX() < 0, aParentScale
.getY() < 0);
956 if(aParentScale
.getX() < 0)
958 if(aParentScale
.getY() < 0)
963 if (maPosition
.X
!= 0 || maPosition
.Y
!= 0)
965 // if global position is used, add it to transformation
966 if (mbWps
&& pParentGroupShape
== nullptr)
967 aTransformation
.translate(
968 o3tl::convert(maPosition
.X
, o3tl::Length::mm100
, o3tl::Length::emu
),
969 o3tl::convert(maPosition
.Y
, o3tl::Length::mm100
, o3tl::Length::emu
));
971 aTransformation
.translate(maPosition
.X
, maPosition
.Y
);
974 // Apply further parent transformations. First scale object then rotate. Other way round would
975 // introduce shearing.
977 // The attributes chExt and chOff of the group in oox file contain the values on which the size
978 // and position of the child is based on. If they differ from the actual size of the group as
979 // given in its ext and off attributes, the child has to be transformed according the new values.
980 if (pParentGroupShape
)
982 // ToDo: A diagram in a group might need special handling because it cannot flip and only
983 // resize uniformly. But currently it is imported with zero size, see tdf#139575. That needs
984 // to be fixed beforehand.
986 // Scaling is done from left/top edges of the group. So these need to become coordinate axes.
987 aTransformation
.translate(-pParentGroupShape
->maChPosition
.X
,
988 -pParentGroupShape
->maChPosition
.Y
);
990 // oox allows zero or missing attribute chExt. In that case the scaling factor is 1.
991 // Transform2DContext::onCreateContext has set maChSize to maSize for groups in oox file in
992 // such cases. For own made groups (e.g. diagrams) that is missing.
993 // The factors cumulate on the way through the parent groups, so we do not use maSize of the
994 // direct parent group but the cumulated value from aParentScale.
995 double fFactorX
= 1.0;
996 double fFactorY
= 1.0;
997 if (pParentGroupShape
->maChSize
.Width
!= 0)
998 fFactorX
= aParentScale
.getX() / pParentGroupShape
->maChSize
.Width
;
999 if (pParentGroupShape
->maChSize
.Height
!= 0)
1000 fFactorY
= aParentScale
.getY() / pParentGroupShape
->maChSize
.Height
;
1001 if (fFactorX
!= 1 || fFactorY
!= 1)
1003 // It depends on the object rotation angle whether scaling is applied to switched
1004 // width and height. MSO acts strange in that case (as of May 2021).
1005 const sal_Int32
nDeg(mnRotation
/ 60000);
1006 const bool bNeedsMSOWidthHeightToggle
1007 = (nDeg
>= 45 && nDeg
< 135) || (nDeg
>= 225 && nDeg
< 315);
1008 if (bNeedsMSOWidthHeightToggle
)
1009 lcl_doSpecialMSOWidthHeightToggle(aTransformation
);
1011 aTransformation
.scale(fFactorX
, fFactorY
);
1013 if (bNeedsMSOWidthHeightToggle
)
1015 lcl_doSpecialMSOWidthHeightToggle(aTransformation
);
1016 // In case of flip the special case needs an additional 180deg rotation.
1017 if ((aParentScale
.getX() < 0) != (aParentScale
.getY() < 0))
1018 lcl_RotateAtCenter(aTransformation
, 10800000);
1023 // Apply object rotation at current object center
1024 // The flip contained in aParentScale will affect orientation of object rotation angle.
1025 sal_Int16 nOrientation
= ((aParentScale
.getX() < 0) != (aParentScale
.getY() < 0)) ? -1 : 1;
1026 // ToDo: Not sure about the restrictions given by bUseRotationTransform.
1027 // Since LibreOffice doesn't have 3D camera options for 2D shapes, rotate the shape opposite of
1028 // the camera Z axis rotation, in order to produce the same visual result from MSO
1029 const sal_Int32 nCameraRotation
= get3DProperties().maCameraRotation
.mnRevolution
.value_or(0);
1030 if (bUseRotationTransform
&& (mnRotation
!= 0 || nCameraRotation
!= 0))
1031 lcl_RotateAtCenter(aTransformation
, nOrientation
* (mnRotation
- nCameraRotation
));
1033 if (fParentRotate
!= 0.0)
1034 aTransformation
.rotate(fParentRotate
);
1035 if (!aParentTranslate
.equalZero())
1036 aTransformation
.translate(aParentTranslate
);
1038 aParentTransformation
= aTransformation
;
1040 constexpr double fEmuToMm100
= o3tl::convert(1.0, o3tl::Length::emu
, o3tl::Length::mm100
);
1041 aTransformation
.scale(fEmuToMm100
, fEmuToMm100
);
1043 // OOXML flips shapes before rotating them, so the rotation needs to be inverted
1044 if( bIsCustomShape
&& mbFlipH
!= mbFlipV
)
1046 basegfx::B2DVector aScale
, aTranslate
;
1047 double fRotate
, fShearX
;
1048 aTransformation
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1052 basegfx::B2DPoint
aCenter(0.5, 0.5);
1053 aCenter
*= aTransformation
;
1054 aTransformation
.translate( -aCenter
.getX(), -aCenter
.getY() );
1055 aTransformation
.rotate( fRotate
* -2.0 );
1056 aTransformation
.translate( aCenter
.getX(), aCenter
.getY() );
1060 // special for lineshape
1061 if ( aServiceName
== "com.sun.star.drawing.LineShape" )
1063 ::basegfx::B2DPolygon aPoly
;
1064 aPoly
.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1065 aPoly
.insert( 1, ::basegfx::B2DPoint( maSize
.Width
? 1 : 0, maSize
.Height
? 1 : 0 ) );
1066 aPoly
.transform( aTransformation
);
1068 // now creating the corresponding PolyPolygon
1069 sal_Int32 i
, nNumPoints
= aPoly
.count();
1070 uno::Sequence
< awt::Point
> aPointSequence( nNumPoints
);
1071 awt::Point
* pPoints
= aPointSequence
.getArray();
1072 for( i
= 0; i
< nNumPoints
; ++i
)
1074 basegfx::B2DPoint
aPoint( aPoly
.getB2DPoint( i
) );
1076 // Guard against zero width or height.
1079 const basegfx::B2DPoint
& rPreviousPoint
= aPoly
.getB2DPoint(i
- 1);
1080 if (aPoint
.getX() - rPreviousPoint
.getX() == 0)
1081 aPoint
.setX(aPoint
.getX() + 1);
1082 if (aPoint
.getY() - rPreviousPoint
.getY() == 0)
1083 aPoint
.setY(aPoint
.getY() + 1);
1086 pPoints
[i
] = awt::Point(static_cast<sal_Int32
>(aPoint
.getX()), static_cast<sal_Int32
>(aPoint
.getY()));
1088 uno::Sequence
< uno::Sequence
< awt::Point
> > aPolyPolySequence( 1 );
1089 aPolyPolySequence
.getArray()[ 0 ] = aPointSequence
;
1091 maShapeProperties
.setProperty(PROP_PolyPolygon
, aPolyPolySequence
);
1093 else if ( aServiceName
== "com.sun.star.drawing.ConnectorShape" )
1095 ::basegfx::B2DPolygon aPoly
;
1096 aPoly
.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1097 aPoly
.insert( 1, ::basegfx::B2DPoint( maSize
.Width
? 1 : 0, maSize
.Height
? 1 : 0 ) );
1098 aPoly
.transform( aTransformation
);
1100 basegfx::B2DPoint
aStartPosition( aPoly
.getB2DPoint( 0 ) );
1101 basegfx::B2DPoint
aEndPosition( aPoly
.getB2DPoint( 1 ) );
1102 awt::Point
aAWTStartPosition( static_cast< sal_Int32
>( aStartPosition
.getX() ), static_cast< sal_Int32
>( aStartPosition
.getY() ) );
1103 awt::Point
aAWTEndPosition( static_cast< sal_Int32
>( aEndPosition
.getX() ), static_cast< sal_Int32
>( aEndPosition
.getY() ) );
1105 maShapeProperties
.setProperty(PROP_StartPosition
, aAWTStartPosition
);
1106 maShapeProperties
.setProperty(PROP_EndPosition
, aAWTEndPosition
);
1110 // now set transformation for this object
1111 HomogenMatrix3 aMatrix
;
1113 aMatrix
.Line1
.Column1
= aTransformation
.get(0,0);
1114 aMatrix
.Line1
.Column2
= aTransformation
.get(0,1);
1115 aMatrix
.Line1
.Column3
= aTransformation
.get(0,2);
1117 aMatrix
.Line2
.Column1
= aTransformation
.get(1,0);
1118 aMatrix
.Line2
.Column2
= aTransformation
.get(1,1);
1119 aMatrix
.Line2
.Column3
= aTransformation
.get(1,2);
1121 aMatrix
.Line3
.Column1
= 0;
1122 aMatrix
.Line3
.Column2
= 0;
1123 aMatrix
.Line3
.Column3
= 1;
1125 maShapeProperties
.setProperty(PROP_Transformation
, aMatrix
);
1128 Reference
< lang::XMultiServiceFactory
> xServiceFact( rFilterBase
.getModel(), UNO_QUERY_THROW
);
1129 if ( !mxShape
.is() )
1131 mxShape
.set( xServiceFact
->createInstance( aServiceName
), UNO_QUERY_THROW
);
1134 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
1137 if( !msName
.isEmpty() )
1139 Reference
< container::XNamed
> xNamed( mxShape
, UNO_QUERY
);
1141 xNamed
->setName( msName
);
1143 if( !msDescription
.isEmpty() )
1145 xSet
->setPropertyValue( "Description", Any( msDescription
) );
1149 xSet
->setPropertyValue("Decorative", Any(m_isDecorative
));
1151 if (aServiceName
!= "com.sun.star.text.TextFrame")
1152 rxShapes
->add( mxShape
);
1154 if ( mbHidden
|| mbHiddenMasterShape
)
1156 SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId
<< "'");
1157 xSet
->setPropertyValue( "Visible", Any( false ) );
1158 // In Excel hidden means not printed, let's use visibility for now until that's handled separately
1159 xSet
->setPropertyValue( "Printable", Any( false ) );
1164 xSet
->setPropertyValue("MoveProtect", Any(true));
1165 xSet
->setPropertyValue("SizeProtect", Any(true));
1168 ActionLockGuard
const alg(mxShape
);
1170 // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape
1173 uno::Reference
< text::XText
> xText( mxShape
, uno::UNO_QUERY
);
1176 xText
->setString( "" );
1182 // the "EmbeddedObject" property is read-only, so we have to create
1183 // the shape first, and it can be read only after the shape is
1184 // inserted into the document, so delay the actual import until here
1185 SvGlobalName
name(SO3_SM_CLASSID
);
1186 xSet
->setPropertyValue("CLSID", uno::Any(name
.GetHexName()));
1187 uno::Reference
<embed::XEmbeddedObject
> const xObj(
1188 xSet
->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY
);
1191 uno::Reference
<uno::XInterface
> const xMathModel(xObj
->getComponent());
1192 oox::FormulaImExportBase
*const pMagic(
1193 dynamic_cast<oox::FormulaImExportBase
*>(xMathModel
.get()));
1195 pMagic
->readFormulaOoxml(*pMathXml
);
1199 const GraphicHelper
& rGraphicHelper
= rFilterBase
.getGraphicHelper();
1201 ::Color
nLinePhClr(ColorTransparency
, 0xffffffff);
1202 ::Color
nFillPhClr(ColorTransparency
, 0xffffffff);
1203 sal_Int16 nFillPhClrTheme
= -1;
1204 sal_Int16 nLinePhClrTheme
= -1;
1205 // TODO: use ph color when applying effect properties
1206 //sal_Int32 nEffectPhClr = -1;
1208 // dmapper needs the original rotation angle for calculating square wrap. This angle is not
1209 // available as property there, so store it in InteropGrabBag.
1210 putPropertyToGrabBag("mso-rotation-angle", Any(mnRotation
));
1214 if( const ShapeStyleRef
* pLineRef
= getShapeStyleRef( XML_lnRef
) )
1216 LineProperties aLineProperties
;
1217 aLineProperties
.maLineFill
.moFillType
= XML_noFill
;
1218 if( const LineProperties
* pLineProps
= pTheme
->getLineStyle( pLineRef
->mnThemedIdx
) )
1219 aLineProperties
.assignUsed( *pLineProps
);
1220 nLinePhClr
= pLineRef
->maPhClr
.getColor( rGraphicHelper
);
1221 nLinePhClrTheme
= pLineRef
->maPhClr
.getSchemeColorIndex();
1223 // Store style-related properties to InteropGrabBag to be able to export them back
1224 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1226 {"SchemeClr", uno::Any(pLineRef
->maPhClr
.getSchemeColorName())},
1227 {"Idx", uno::Any(pLineRef
->mnThemedIdx
)},
1228 {"Color", uno::Any(nLinePhClr
)},
1229 {"LineStyle", uno::Any(aLineProperties
.getLineStyle())},
1230 {"LineCap", uno::Any(aLineProperties
.getLineCap())},
1231 {"LineJoint", uno::Any(aLineProperties
.getLineJoint())},
1232 {"LineWidth", uno::Any(aLineProperties
.getLineWidth())},
1233 {"Transformations", uno::Any(pLineRef
->maPhClr
.getTransformations())}
1235 putPropertyToGrabBag( "StyleLnRef", Any( aProperties
) );
1237 if( const ShapeStyleRef
* pFillRef
= getShapeStyleRef( XML_fillRef
) )
1239 if (!getFillProperties().moUseBgFill
.value_or(false))
1241 nFillPhClr
= pFillRef
->maPhClr
.getColor(rGraphicHelper
);
1242 nFillPhClrTheme
= pFillRef
->maPhClr
.getSchemeColorIndex();
1245 OUString sColorScheme
= pFillRef
->maPhClr
.getSchemeColorName();
1246 if( !sColorScheme
.isEmpty() )
1248 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1250 {"SchemeClr", uno::Any(sColorScheme
)},
1251 {"Idx", uno::Any(pFillRef
->mnThemedIdx
)},
1252 {"Color", uno::Any(nFillPhClr
)},
1253 {"Transformations", uno::Any(pFillRef
->maPhClr
.getTransformations())}
1256 putPropertyToGrabBag( "StyleFillRef", Any( aProperties
) );
1259 if( const ShapeStyleRef
* pEffectRef
= getShapeStyleRef( XML_effectRef
) )
1261 // TODO: use ph color when applying effect properties
1262 // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper );
1264 // Store style-related properties to InteropGrabBag to be able to export them back
1265 uno::Sequence
<beans::PropertyValue
> aProperties
= comphelper::InitPropertySequence(
1267 {"SchemeClr", uno::Any(pEffectRef
->maPhClr
.getSchemeColorName())},
1268 {"Idx", uno::Any(pEffectRef
->mnThemedIdx
)},
1269 {"Transformations", uno::Any(pEffectRef
->maPhClr
.getTransformations())}
1271 putPropertyToGrabBag( "StyleEffectRef", Any( aProperties
) );
1274 ShapePropertyMap
aShapeProps( rFilterBase
.getModelObjectHelper() );
1276 // add properties from textbody to shape properties
1279 mpTextBody
->getTextProperties().pushTextDistances(Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
));
1280 aShapeProps
.assignUsed( mpTextBody
->getTextProperties().maPropertyMap
);
1281 // Push char properties as well - specifically useful when this is a placeholder
1282 if( mpMasterTextListStyle
&& mpMasterTextListStyle
->getListStyle()[0].getTextCharacterProperties().moHeight
.has_value() )
1283 aShapeProps
.setProperty(PROP_CharHeight
, GetFontHeight( mpMasterTextListStyle
->getListStyle()[0].getTextCharacterProperties().moHeight
.value() ));
1286 // applying properties
1287 aShapeProps
.assignUsed( getShapeProperties() );
1288 aShapeProps
.assignUsed( maDefaultShapeProperties
);
1289 if(mnRotation
!= 0 && bIsCustomShape
)
1290 aShapeProps
.setProperty( PROP_RotateAngle
, sal_Int32( NormAngle36000( Degree100(mnRotation
/ -600) ) ));
1293 aServiceName
== "com.sun.star.drawing.GraphicObjectShape" ||
1294 aServiceName
== "com.sun.star.drawing.OLE2Shape")
1296 mpGraphicPropertiesPtr
->pushToPropMap( aShapeProps
, rGraphicHelper
, mbFlipH
, mbFlipV
);
1298 if ( mpTablePropertiesPtr
&& aServiceName
== "com.sun.star.drawing.TableShape" )
1300 mpTablePropertiesPtr
->pushToPropSet( rFilterBase
, xSet
, mpMasterTextListStyle
);
1301 if ( auto* pTableShape
= dynamic_cast<sdr::table::SdrTableObj
*>(SdrObject::getSdrObjectFromXShape(mxShape
)) )
1303 // Disable layouting until table height is expanded to fit the content
1304 pTableShape
->SetSkipChangeLayout(true);
1308 FillProperties aFillProperties
= getActualFillProperties(pTheme
, &rShapeOrParentShapeFillProps
);
1309 if (getFillProperties().moFillType
.has_value() && getFillProperties().moFillType
.value() == XML_grpFill
)
1310 getFillProperties().assignUsed(aFillProperties
);
1311 if(!bIsCroppedGraphic
)
1312 aFillProperties
.pushToPropMap(aShapeProps
, rGraphicHelper
, mnRotation
, nFillPhClr
,
1313 css::awt::Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
),
1314 nFillPhClrTheme
, mbFlipH
, mbFlipV
, bIsCustomShape
);
1316 LineProperties aLineProperties
= getActualLineProperties(pTheme
);
1317 aLineProperties
.pushToPropMap( aShapeProps
, rGraphicHelper
, nLinePhClr
, nLinePhClrTheme
);
1318 EffectProperties aEffectProperties
= getActualEffectProperties(pTheme
);
1319 // TODO: use ph color when applying effect properties
1320 aEffectProperties
.pushToPropMap( aShapeProps
, rGraphicHelper
);
1322 // applying autogrowheight property before setting shape size, because
1323 // the shape size might be changed if currently autogrowheight is true
1324 // we must also check that the PropertySet supports the property.
1325 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
1326 const OUString
& rPropName
= PropertyMap::getPropertyName( PROP_TextAutoGrowHeight
);
1327 if( xSetInfo
.is() && xSetInfo
->hasPropertyByName( rPropName
) )
1328 if( aShapeProps
.hasProperty( PROP_TextAutoGrowHeight
) )
1329 xSet
->setPropertyValue( rPropName
, Any( false ) );
1331 // do not set properties at a group shape (this causes
1332 // assertions from svx) ...
1333 if( aServiceName
!= "com.sun.star.drawing.GroupShape" )
1335 if (aServiceName
== "com.sun.star.text.TextFrame")
1337 if (mpCustomShapePropertiesPtr
&& mpCustomShapePropertiesPtr
->getShapeTypeOverride())
1339 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1340 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1341 propertySet
->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag
;
1342 sal_Int32 length
= aGrabBag
.getLength();
1343 aGrabBag
.realloc( length
+1);
1344 auto pGrabBag
= aGrabBag
.getArray();
1345 pGrabBag
[length
].Name
= "mso-orig-shape-type";
1346 uno::Sequence
< sal_Int8
> const & aNameSeq
=
1347 mpCustomShapePropertiesPtr
->getShapePresetTypeName();
1348 OUString
sShapePresetTypeName(reinterpret_cast< const char* >(
1349 aNameSeq
.getConstArray()), aNameSeq
.getLength(), RTL_TEXTENCODING_UTF8
);
1350 pGrabBag
[length
].Value
<<= sShapePresetTypeName
;
1351 propertySet
->setPropertyValue("FrameInteropGrabBag",uno::Any(aGrabBag
));
1353 //If the text box has links then save the link information so that
1354 //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames.
1357 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1358 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1359 propertySet
->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag
;
1360 sal_Int32 length
= aGrabBag
.getLength();
1361 aGrabBag
.realloc( length
+ 3 );
1362 auto pGrabBag
= aGrabBag
.getArray();
1363 pGrabBag
[length
].Name
= "TxbxHasLink";
1364 pGrabBag
[length
].Value
<<= isLinkedTxbx();
1365 pGrabBag
[length
+ 1 ].Name
= "Txbx-Id";
1366 pGrabBag
[length
+ 1 ].Value
<<= getLinkedTxbxAttributes().id
;
1367 pGrabBag
[length
+ 2 ].Name
= "Txbx-Seq";
1368 pGrabBag
[length
+ 2 ].Value
<<= getLinkedTxbxAttributes().seq
;
1369 propertySet
->setPropertyValue("FrameInteropGrabBag",uno::Any(aGrabBag
));
1372 // TextFrames have BackColor, not FillColor
1373 if (aShapeProps
.hasProperty(PROP_FillColor
))
1375 aShapeProps
.setAnyProperty(PROP_BackColor
, aShapeProps
.getProperty(PROP_FillColor
));
1376 aShapeProps
.erase(PROP_FillColor
);
1378 // TextFrames have BackColorTransparency, not FillTransparence
1379 if (aShapeProps
.hasProperty(PROP_FillTransparence
))
1381 aShapeProps
.setAnyProperty(PROP_BackColorTransparency
, aShapeProps
.getProperty(PROP_FillTransparence
));
1382 aShapeProps
.erase(PROP_FillTransparence
);
1384 // TextFrames have BackGraphic, not FillBitmap
1385 if (aShapeProps
.hasProperty(PROP_FillBitmap
))
1387 aShapeProps
.setAnyProperty(PROP_BackGraphic
, aShapeProps
.getProperty(PROP_FillBitmap
));
1388 aShapeProps
.erase(PROP_FillBitmap
);
1390 if (aShapeProps
.hasProperty(PROP_FillBitmapName
))
1392 uno::Any aAny
= aShapeProps
.getProperty(PROP_FillBitmapName
);
1393 OUString aFillBitmapName
= aAny
.get
<OUString
>();
1394 uno::Reference
<awt::XBitmap
> xBitmap
= rFilterBase
.getModelObjectHelper().getFillBitmap(aFillBitmapName
);
1395 uno::Reference
<graphic::XGraphic
> xGraphic(xBitmap
, uno::UNO_QUERY
);
1396 aShapeProps
.setProperty(PROP_BackGraphic
, xGraphic
);
1397 // aShapeProps.erase(PROP_FillBitmapName); // Maybe, leave the name as well
1399 // And no LineColor property; individual borders can have colors
1400 if (aShapeProps
.hasProperty(PROP_LineColor
))
1402 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
1403 static const sal_Int32 aBorders
[] =
1405 PROP_TopBorder
, PROP_LeftBorder
, PROP_BottomBorder
, PROP_RightBorder
1407 for (sal_Int32 nBorder
: aBorders
)
1409 css::table::BorderLine2 aBorderLine
= xPropertySet
->getPropertyValue(PropertyMap::getPropertyName(nBorder
)).get
<css::table::BorderLine2
>();
1410 aBorderLine
.Color
= aShapeProps
.getProperty(PROP_LineColor
).get
<sal_Int32
>();
1411 if (aLineProperties
.moLineWidth
.has_value())
1412 aBorderLine
.LineWidth
= convertEmuToHmm(aLineProperties
.moLineWidth
.value());
1413 aShapeProps
.setProperty(nBorder
, aBorderLine
);
1415 aShapeProps
.erase(PROP_LineColor
);
1419 uno::Reference
<beans::XPropertySet
> xPropertySet(mxShape
, uno::UNO_QUERY
);
1420 static const OUStringLiteral aGrabBagPropName
= u
"FrameInteropGrabBag";
1421 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1422 xPropertySet
->getPropertyValue(aGrabBagPropName
) >>= aGrabBag
;
1423 beans::PropertyValue
aPair(comphelper::makePropertyValue("mso-rotation-angle",
1425 if (aGrabBag
.hasElements())
1427 sal_Int32 nLength
= aGrabBag
.getLength();
1428 aGrabBag
.realloc(nLength
+ 1);
1429 aGrabBag
.getArray()[nLength
] = aPair
;
1433 aGrabBag
= { aPair
};
1435 xPropertySet
->setPropertyValue(aGrabBagPropName
, uno::Any(aGrabBag
));
1437 // TextFrames have ShadowFormat, not individual shadow properties.
1438 std::optional
<sal_Int32
> oShadowDistance
;
1439 if (aShapeProps
.hasProperty(PROP_ShadowXDistance
))
1441 oShadowDistance
= aShapeProps
.getProperty(PROP_ShadowXDistance
).get
<sal_Int32
>();
1442 aShapeProps
.erase(PROP_ShadowXDistance
);
1444 if (aShapeProps
.hasProperty(PROP_ShadowYDistance
))
1446 // There is a single 'dist' attribute, so no need to count the avg of x and y.
1447 aShapeProps
.erase(PROP_ShadowYDistance
);
1449 std::optional
<sal_Int32
> oShadowColor
;
1450 if (aShapeProps
.hasProperty(PROP_ShadowColor
))
1452 oShadowColor
= aShapeProps
.getProperty(PROP_ShadowColor
).get
<sal_Int32
>();
1453 aShapeProps
.erase(PROP_ShadowColor
);
1455 if (aShapeProps
.hasProperty(PROP_Shadow
))
1456 aShapeProps
.erase(PROP_Shadow
);
1458 if (oShadowDistance
|| oShadowColor
|| aEffectProperties
.maShadow
.moShadowDir
.has_value())
1460 css::table::ShadowFormat aFormat
;
1462 aFormat
.Color
= *oShadowColor
;
1463 if (aEffectProperties
.maShadow
.moShadowDir
.has_value())
1465 css::table::ShadowLocation nLocation
= css::table::ShadowLocation_NONE
;
1466 switch (aEffectProperties
.maShadow
.moShadowDir
.value())
1469 nLocation
= css::table::ShadowLocation_TOP_LEFT
;
1472 nLocation
= css::table::ShadowLocation_TOP_RIGHT
;
1475 nLocation
= css::table::ShadowLocation_BOTTOM_LEFT
;
1478 nLocation
= css::table::ShadowLocation_BOTTOM_RIGHT
;
1481 aFormat
.Location
= nLocation
;
1483 aFormat
.ShadowWidth
= *oShadowDistance
;
1484 aShapeProps
.setProperty(PROP_ShadowFormat
, aFormat
);
1490 // This introduces a TextBox in a shape in Writer. ToDo: Can we restrict it to cases
1491 // where the TextBox edit engine is really needed? tdf#82627
1492 aShapeProps
.setProperty(PROP_TextBox
, true);
1495 if (aServiceName
!= "com.sun.star.text.TextFrame" && isLinkedTxbx())
1497 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1498 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1499 propertySet
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
1500 sal_Int32 length
= aGrabBag
.getLength();
1501 aGrabBag
.realloc( length
+ 3 );
1502 auto pGrabBag
= aGrabBag
.getArray();
1503 pGrabBag
[length
].Name
= "TxbxHasLink";
1504 pGrabBag
[length
].Value
<<= isLinkedTxbx();
1505 pGrabBag
[length
+ 1 ].Name
= "Txbx-Id";
1506 pGrabBag
[length
+ 1 ].Value
<<= getLinkedTxbxAttributes().id
;
1507 pGrabBag
[length
+ 2 ].Name
= "Txbx-Seq";
1508 pGrabBag
[length
+ 2 ].Value
<<= getLinkedTxbxAttributes().seq
;
1509 propertySet
->setPropertyValue("InteropGrabBag",uno::Any(aGrabBag
));
1512 // If the shape is a picture placeholder.
1513 if (aServiceName
== "com.sun.star.presentation.GraphicObjectShape" && !bClearText
)
1515 // Placeholder text should be in center of the shape.
1516 aShapeProps
.setProperty(PROP_TextContourFrame
, false);
1518 /* Placeholder icon should be at the center of the parent shape.
1519 * We use negative graphic crop property because of that we don't
1520 * have padding support.
1522 uno::Reference
<beans::XPropertySet
> xGraphic(xSet
->getPropertyValue("Graphic"), uno::UNO_QUERY
);
1525 awt::Size aBitmapSize
;
1526 xGraphic
->getPropertyValue("Size100thMM") >>= aBitmapSize
;
1527 sal_Int32 nXMargin
= (aShapeRectHmm
.Width
- aBitmapSize
.Width
) / 2;
1528 sal_Int32 nYMargin
= (aShapeRectHmm
.Height
- aBitmapSize
.Height
) / 2;
1529 if (nXMargin
> 0 && nYMargin
> 0)
1531 text::GraphicCrop aGraphicCrop
;
1532 aGraphicCrop
.Top
= nYMargin
* -1;
1533 aGraphicCrop
.Bottom
= nYMargin
* -1;
1534 aGraphicCrop
.Left
= nXMargin
* -1;
1535 aGraphicCrop
.Right
= nXMargin
* -1;
1536 aShapeProps
.setProperty(PROP_GraphicCrop
, aGraphicCrop
);
1541 PropertySet( xSet
).setProperties( aShapeProps
);
1543 if (mpTablePropertiesPtr
&& aServiceName
== "com.sun.star.drawing.TableShape")
1545 // Powerpoint exports desired row heights (i.e. what user attempted to set it as, not how it appears visually)
1546 // Expand table height if there are rows that can't fit the content
1547 if (auto* pTableShape
= dynamic_cast<sdr::table::SdrTableObj
*>(SdrObject::getSdrObjectFromXShape(mxShape
)))
1549 tools::Rectangle aArea
{};
1550 pTableShape
->LayoutTableHeight(aArea
, /*bFit=*/false);
1551 sal_Int32 nCorrectedHeight
= aArea
.GetHeight();
1552 const auto& aShapeSize
= mxShape
->getSize();
1553 if( nCorrectedHeight
> aShapeSize
.Height
)
1554 mxShape
->setSize( {aShapeSize
.Width
, nCorrectedHeight
} );
1555 pTableShape
->SetSkipChangeLayout(false);
1561 putPropertyToGrabBag( "LockedCanvas", Any( true ) );
1562 if (aServiceName
== "com.sun.star.drawing.LineShape")
1564 // It seems the position and size for lines inside a locked canvas is absolute.
1565 mxShape
->setPosition(awt::Point(aShapeRectHmm
.X
, aShapeRectHmm
.Y
));
1566 mxShape
->setSize(awt::Size(aShapeRectHmm
.Width
, aShapeRectHmm
.Height
));
1570 // Store original fill and line colors of the shape and the theme color name to InteropGrabBag
1571 std::vector
<beans::PropertyValue
> aProperties
1573 comphelper::makePropertyValue("EmuLineWidth", aLineProperties
.moLineWidth
.value_or(0)),
1574 comphelper::makePropertyValue("OriginalSolidFillClr", aShapeProps
.getProperty(PROP_FillColor
)),
1575 comphelper::makePropertyValue("OriginalLnSolidFillClr", aShapeProps
.getProperty(PROP_LineColor
))
1577 OUString sColorFillScheme
= aFillProperties
.maFillColor
.getSchemeColorName();
1578 if( !aFillProperties
.maFillColor
.isPlaceHolder() && !sColorFillScheme
.isEmpty() )
1580 aProperties
.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClr", sColorFillScheme
));
1581 aProperties
.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClrTransformations", aFillProperties
.maFillColor
.getTransformations()));
1583 OUString sLnColorFillScheme
= aLineProperties
.maLineFill
.maFillColor
.getSchemeColorName();
1584 if( !aLineProperties
.maLineFill
.maFillColor
.isPlaceHolder() && !sLnColorFillScheme
.isEmpty() )
1586 aProperties
.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClr", sLnColorFillScheme
));
1587 auto aResolvedSchemeClr
= aLineProperties
.maLineFill
.maFillColor
;
1588 aResolvedSchemeClr
.clearTransformations();
1589 aProperties
.push_back(comphelper::makePropertyValue("SpPrLnSolidFillResolvedSchemeClr", aResolvedSchemeClr
.getColor(rGraphicHelper
, nFillPhClr
)));
1590 aProperties
.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClrTransformations", aLineProperties
.maLineFill
.maFillColor
.getTransformations()));
1592 putPropertiesToGrabBag(comphelper::containerToSequence(aProperties
));
1594 // Store original gradient fill of the shape to InteropGrabBag
1595 // LibreOffice doesn't support all the kinds of gradient so we save its complete definition
1596 if( aShapeProps
.hasProperty( PROP_FillGradient
) )
1598 std::vector
<beans::PropertyValue
> aGradientStops
;
1600 for( const auto& [rPos
, rColor
] : aFillProperties
.maGradientProps
.maGradientStops
)
1601 { // for each stop in the gradient definition:
1604 std::vector
<beans::PropertyValue
> aGradientStop
1606 comphelper::makePropertyValue("Pos", rPos
)
1609 OUString sStopColorScheme
= rColor
.getSchemeColorName();
1610 if( sStopColorScheme
.isEmpty() )
1613 aGradientStop
.push_back(comphelper::makePropertyValue("RgbClr", rColor
.getColor(rGraphicHelper
, nFillPhClr
)));
1614 // in the case of a RGB color, transformations are already applied to
1615 // the color with the exception of alpha transformations. We only need
1616 // to keep the transparency value to calculate the alpha value later.
1617 if( rColor
.hasTransparency() )
1618 aGradientStop
.push_back(comphelper::makePropertyValue("Transparency", rColor
.getTransparency()));
1622 // save color with scheme name
1623 aGradientStop
.push_back(comphelper::makePropertyValue("SchemeClr", sStopColorScheme
));
1624 // save all color transformations
1625 aGradientStop
.push_back(comphelper::makePropertyValue("Transformations", rColor
.getTransformations()));
1628 aGradientStops
.push_back(comphelper::makePropertyValue(OUString::number(i
), comphelper::containerToSequence(aGradientStop
)));
1631 // If getFillProperties.moFillType is unused that means gradient is defined by a theme
1632 // which is already saved into StyleFillRef property, so no need to save the explicit values too
1633 if( getFillProperties().moFillType
.has_value() )
1634 putPropertyToGrabBag( "GradFillDefinition", uno::Any(comphelper::containerToSequence(aGradientStops
)));
1635 putPropertyToGrabBag( "OriginalGradFill", aShapeProps
.getProperty(PROP_FillGradient
) );
1638 // store unsupported effect attributes in the grab bag
1639 if (!aEffectProperties
.m_Effects
.empty())
1641 std::vector
<beans::PropertyValue
> aEffects
;
1642 for (auto const& it
: aEffectProperties
.m_Effects
)
1644 PropertyValue aEffect
= it
->getEffect();
1645 if( !aEffect
.Name
.isEmpty() )
1647 std::vector
<beans::PropertyValue
> aEffectsGrabBag
1649 comphelper::makePropertyValue("Attribs", aEffect
.Value
)
1652 Color
& aColor( it
->moColor
);
1653 OUString sColorScheme
= aColor
.getSchemeColorName();
1654 if( sColorScheme
.isEmpty() )
1656 // RGB color and transparency value
1657 aEffectsGrabBag
.push_back(comphelper::makePropertyValue("RgbClr", aColor
.getColor(rGraphicHelper
, nFillPhClr
)));
1658 aEffectsGrabBag
.push_back(comphelper::makePropertyValue("RgbClrTransparency", aColor
.getTransparency()));
1662 // scheme color with name and transformations
1663 aEffectsGrabBag
.push_back(comphelper::makePropertyValue("SchemeClr", sColorScheme
));
1664 aEffectsGrabBag
.push_back(comphelper::makePropertyValue("SchemeClrTransformations", aColor
.getTransformations()));
1666 aEffects
.push_back(comphelper::makePropertyValue(aEffect
.Name
, comphelper::containerToSequence(aEffectsGrabBag
)));
1669 putPropertyToGrabBag("EffectProperties", uno::Any(comphelper::containerToSequence(aEffects
)));
1672 // add 3D effects if any
1673 Sequence
< PropertyValue
> aCamera3DEffects
= get3DProperties().getCameraAttributes();
1674 Sequence
< PropertyValue
> aLightRig3DEffects
= get3DProperties().getLightRigAttributes();
1675 Sequence
< PropertyValue
> aShape3DEffects
= get3DProperties().getShape3DAttributes( rGraphicHelper
, nFillPhClr
);
1676 if( aCamera3DEffects
.hasElements() || aLightRig3DEffects
.hasElements() || aShape3DEffects
.hasElements() )
1678 uno::Sequence
<beans::PropertyValue
> a3DEffectsGrabBag
= comphelper::InitPropertySequence(
1680 {"Camera", uno::Any(aCamera3DEffects
)},
1681 {"LightRig", uno::Any(aLightRig3DEffects
)},
1682 {"Shape3D", uno::Any(aShape3DEffects
)}
1684 putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag
) );
1687 if( bIsCustomShape
&& getTextBody())
1690 Sequence
< PropertyValue
> aTextCamera3DEffects
= getTextBody()->get3DProperties().getCameraAttributes();
1691 Sequence
< PropertyValue
> aTextLightRig3DEffects
= getTextBody()->get3DProperties().getLightRigAttributes();
1692 Sequence
< PropertyValue
> aTextShape3DEffects
= getTextBody()->get3DProperties().getShape3DAttributes( rGraphicHelper
, nFillPhClr
);
1693 if( aTextCamera3DEffects
.hasElements() || aTextLightRig3DEffects
.hasElements() || aTextShape3DEffects
.hasElements() )
1695 uno::Sequence
<beans::PropertyValue
> aText3DEffectsGrabBag
= comphelper::InitPropertySequence(
1697 {"Camera", uno::Any(aTextCamera3DEffects
)},
1698 {"LightRig", uno::Any(aTextLightRig3DEffects
)},
1699 {"Shape3D", uno::Any(aTextShape3DEffects
)}
1701 putPropertyToGrabBag( "Text3DEffectProperties", Any( aText3DEffectsGrabBag
) );
1705 // store bitmap artistic effects in the grab bag
1706 if( !mpGraphicPropertiesPtr
->maBlipProps
.maEffect
.isEmpty() )
1707 putPropertyToGrabBag( "ArtisticEffectProperties",
1708 Any( mpGraphicPropertiesPtr
->maBlipProps
.maEffect
.getEffect() ) );
1711 else if( mbLockedCanvas
)
1713 //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas
1714 putPropertyToGrabBag( "LockedCanvas", Any( true ) );
1717 // These can have a custom geometry, so position should be set here,
1718 // after creation but before custom shape handling, using the position
1719 // we got from the caller.
1720 if (mbWps
&& aServiceName
== "com.sun.star.drawing.LineShape" && !pParentGroupShape
)
1721 mxShape
->setPosition(maPosition
);
1723 if (bIsConnectorShape
)
1725 OUString
sConnectorShapePresetTypeName(
1726 reinterpret_cast<const char*>(
1727 mpCustomShapePropertiesPtr
->getShapePresetTypeName().getConstArray()),
1728 mpCustomShapePropertiesPtr
->getShapePresetTypeName().getLength(),
1729 RTL_TEXTENCODING_UTF8
);
1730 msConnectorName
= sConnectorShapePresetTypeName
;
1732 auto aAdjustmentList
= mpCustomShapePropertiesPtr
->getAdjustmentGuideList();
1733 for (size_t i
= 0; i
< aAdjustmentList
.size(); i
++)
1734 maConnectorAdjustmentList
.push_back(aAdjustmentList
[i
].maFormula
);
1736 sal_Int32 nType
= mpCustomShapePropertiesPtr
->getShapePresetType();
1740 case XML_straightConnector1
:
1741 xSet
->setPropertyValue("EdgeKind", Any(ConnectorType_LINE
));
1743 case XML_bentConnector2
:
1744 case XML_bentConnector3
:
1745 case XML_bentConnector4
:
1746 case XML_bentConnector5
:
1747 xSet
->setPropertyValue("EdgeKind", Any(ConnectorType_STANDARD
));
1749 case XML_curvedConnector2
:
1750 case XML_curvedConnector3
:
1751 case XML_curvedConnector4
:
1752 case XML_curvedConnector5
:
1753 xSet
->setPropertyValue("EdgeKind", Any(ConnectorType_CURVE
));
1760 if( bIsCustomShape
)
1763 mpCustomShapePropertiesPtr
->setMirroredX( true );
1765 mpCustomShapePropertiesPtr
->setMirroredY( true );
1768 sal_Int32 nTextCameraZRotation
= getTextBody()->get3DProperties().maCameraRotation
.mnRevolution
.value_or(0);
1769 mpCustomShapePropertiesPtr
->setTextCameraZRotateAngle( nTextCameraZRotation
/ 60000 );
1771 // TextPreRotateAngle. Text rotates inside the text area. Might be used for diagram layout 'upr' and 'grav'.
1772 sal_Int32 nTextPreRotateAngle
= static_cast< sal_Int32
>( getTextBody()->getTextProperties().moTextPreRotation
.value_or( 0 ) );
1774 nTextPreRotateAngle
-= mnDiagramRotation
; // Use of mnDiagramRotation is unclear. It seems to be always 0 here.
1776 // TextRotateAngle. The text area rotates.
1777 sal_Int32 nTextAreaRotateAngle
= getTextBody()->getTextProperties().moTextAreaRotation
.value_or(0);
1778 if (getTextBody()->getTextProperties().moUpright
)
1780 // When upright is set, any text area transformation and shape rotation is ignored
1781 // in MS Office. To simulate this behaviour, we rotate the text area into the
1782 // opposite direction of the shape rotation by as much as the shape was rotated
1783 // and so compensate the shape rotation, which is added in rendering.
1784 nTextAreaRotateAngle
= -mnRotation
;
1785 // If 45° <= shape rotation < 135° or 225° <= shape rotation < 315°,
1786 // then MS Office adds an additional 90° rotation to the text area.
1787 const sal_Int32
nDeg(mnRotation
/ 60000);
1788 if ((nDeg
>= 45 && nDeg
< 135) || (nDeg
>= 225 && nDeg
< 315))
1790 nTextAreaRotateAngle
+= 5400000;
1791 nTextPreRotateAngle
-= 5400000; // compensate the additional text area rotation
1793 putPropertyToGrabBag("Upright", Any(true));
1795 /* OOX measures text rotation clockwise in 1/60000th degrees,
1796 relative to the containing shape. set*Angle wants degrees counter-clockwise. */
1797 mpCustomShapePropertiesPtr
->setTextPreRotateAngle(-nTextPreRotateAngle
/ 60000);
1798 if (nTextAreaRotateAngle
!= 0)
1799 mpCustomShapePropertiesPtr
->setTextAreaRotateAngle(-nTextAreaRotateAngle
/ 60000);
1801 auto sHorzOverflow
= getTextBody()->getTextProperties().msHorzOverflow
;
1802 if (!sHorzOverflow
.isEmpty())
1803 putPropertyToGrabBag("horzOverflow", uno::Any(getTextBody()->getTextProperties().msHorzOverflow
));
1804 if (XML_ellipsis
== getTextBody()->getTextProperties().moVertOverflow
)
1805 putPropertyToGrabBag("vertOverflow", uno::Any(OUString
{"ellipsis"}));
1808 // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks
1809 // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs
1810 SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName
<< "'");
1811 SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName
<< "'");
1813 mpCustomShapePropertiesPtr
->pushToPropSet(xSet
, maSize
);
1816 if (mpTextBody
&& !mpTextBody
->getTextProperties().msPrst
.isEmpty()
1817 && mpTextBody
->getTextProperties().msPrst
!= u
"textNoShape")
1819 bool bFromWordArt(aShapeProps
.hasProperty(PROP_FromWordArt
)
1820 ? aShapeProps
.getProperty(PROP_FromWordArt
).get
<bool>()
1822 FontworkHelpers::putCustomShapeIntoTextPathMode(
1823 mxShape
, mpCustomShapePropertiesPtr
, mpTextBody
->getTextProperties().msPrst
,
1827 else if( getTextBody() )
1828 getTextBody()->getTextProperties().pushVertSimulation();
1830 // tdf#133037: a bit hackish: force Shape to rotate in the opposite direction the camera would rotate
1831 PropertySet
aPropertySet(mxShape
);
1832 if ( !bUseRotationTransform
&& (mnRotation
!= 0 || nCameraRotation
!= 0) )
1834 // use the same logic for rotation from VML exporter (SimpleShape::implConvertAndInsert at vmlshape.cxx)
1835 Degree100 nAngle
= NormAngle36000( Degree100((mnRotation
- nCameraRotation
) / -600) );
1836 aPropertySet
.setAnyProperty( PROP_RotateAngle
, Any( sal_Int32( nAngle
.get() ) ) );
1837 aPropertySet
.setAnyProperty( PROP_HoriOrientPosition
, Any( maPosition
.X
) );
1838 aPropertySet
.setAnyProperty( PROP_VertOrientPosition
, Any( maPosition
.Y
) );
1841 // in some cases, we don't have any text body.
1842 if( mpTextBody
&& ( !bDoNotInsertEmptyTextBody
|| !mpTextBody
->isEmpty() ) )
1844 Reference
< XText
> xText( mxShape
, UNO_QUERY
);
1845 if ( xText
.is() ) // not every shape is supporting an XText interface (e.g. GroupShape)
1847 TextCharacterProperties aCharStyleProperties
;
1848 if( const ShapeStyleRef
* pFontRef
= getShapeStyleRef( XML_fontRef
) )
1850 if( pFontRef
->mnThemedIdx
!= 0 )
1853 if( const TextCharacterProperties
* pCharProps
= pTheme
->getFontStyle( pFontRef
->mnThemedIdx
) )
1854 aCharStyleProperties
.assignUsed( *pCharProps
);
1855 SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color");
1856 if ( pFontRef
->maPhClr
.isUsed() )
1858 aCharStyleProperties
.maFillProperties
.maFillColor
= pFontRef
->maPhClr
;
1859 aCharStyleProperties
.maFillProperties
.moFillType
= XML_solidFill
;
1863 xText
->setString("");
1864 Reference
< XTextCursor
> xAt
= xText
->createTextCursor();
1865 getTextBody()->insertAt( rFilterBase
, xText
, xAt
, aCharStyleProperties
, mpMasterTextListStyle
);
1867 const TextParagraphVector
& rParagraphs
= getTextBody()->getParagraphs();
1868 if (!rParagraphs
.empty())
1870 const std::shared_ptr
<TextParagraph
>& pParagraph
= rParagraphs
[0];
1871 if (pParagraph
->getProperties().getParaAdjust())
1873 style::ParagraphAdjust eAdjust
= *pParagraph
->getProperties().getParaAdjust();
1874 if (eAdjust
== style::ParagraphAdjust_CENTER
)
1876 // If the first paragraph is centered, then set the para adjustment of
1877 // the shape itself to centered as well.
1878 aPropertySet
.setAnyProperty(PROP_ParaAdjust
, uno::Any(eAdjust
));
1882 // tdf#144092 For empty textboxes push character styles &
1883 // endParaRPr into the Shape's properties
1884 if (rParagraphs
.size() == 1 && pParagraph
->getRuns().empty())
1886 TextCharacterProperties aTextCharacterProps
{ pParagraph
->getCharacterStyle(
1887 aCharStyleProperties
, *mpMasterTextListStyle
,
1888 getTextBody()->getTextListStyle()) };
1889 aTextCharacterProps
.assignUsed(pParagraph
->getEndProperties());
1890 aTextCharacterProps
.pushToPropSet(aPropertySet
, rFilterBase
);
1894 // MS Office has e.g. fill and stroke of WordArt in the character properties,
1895 // LibreOffice uses shape properties.
1896 if (!mpTextBody
->getTextProperties().msPrst
.isEmpty()
1897 && mpTextBody
->getTextProperties().msPrst
!= u
"textNoShape")
1899 lcl_copyCharPropsToShape(mxShape
, mpTextBody
, rFilterBase
);
1905 // No drawingML text, but WPS text is expected: save the theme
1906 // character color on the shape, then.
1907 if(const ShapeStyleRef
* pFontRef
= getShapeStyleRef(XML_fontRef
))
1909 ::Color nCharColor
= pFontRef
->maPhClr
.getColor(rGraphicHelper
);
1910 aPropertySet
.setAnyProperty(PROP_CharColor
, uno::Any(nCharColor
));
1914 // Set glow effect properties
1915 if (aEffectProperties
.maGlow
.moGlowRad
.has_value()
1916 && aServiceName
!= "com.sun.star.drawing.GroupShape")
1918 uno::Reference
<beans::XPropertySet
> propertySet (mxShape
, uno::UNO_QUERY
);
1919 propertySet
->setPropertyValue("GlowEffectRadius", Any(convertEmuToHmm(aEffectProperties
.maGlow
.moGlowRad
.value())));
1920 propertySet
->setPropertyValue("GlowEffectColor", Any(aEffectProperties
.maGlow
.moGlowColor
.getColor(rGraphicHelper
)));
1921 propertySet
->setPropertyValue("GlowEffectTransparency", Any(aEffectProperties
.maGlow
.moGlowColor
.getTransparency()));
1924 // Set soft edge effect properties
1925 if (aEffectProperties
.maSoftEdge
.moRad
.has_value())
1927 uno::Reference
<beans::XPropertySet
> propertySet(mxShape
, uno::UNO_QUERY
);
1928 propertySet
->setPropertyValue(
1929 "SoftEdgeRadius", Any(convertEmuToHmm(aEffectProperties
.maSoftEdge
.moRad
.value())));
1932 // Set the stroke and fill-color properties of the OLE shape
1933 if (aServiceName
== "com.sun.star.drawing.OLE2Shape" && mxOleObjectInfo
1934 && !mxOleObjectInfo
->maShapeId
.isEmpty())
1935 if (::oox::vml::Drawing
* pVmlDrawing
= rFilterBase
.getVmlDrawing())
1936 if (const ::oox::vml::ShapeBase
* pVmlShape
1937 = pVmlDrawing
->getShapes().getShapeById(mxOleObjectInfo
->maShapeId
))
1939 // Apply stroke props from the type model of the related VML shape.
1940 ShapePropertyMap
aPropMap(rFilterBase
.getModelObjectHelper());
1941 pVmlShape
->getTypeModel().maStrokeModel
.pushToPropMap(
1942 aPropMap
, rFilterBase
.getGraphicHelper());
1943 // And, fill-color properties as well...
1944 pVmlShape
->getTypeModel().maFillModel
.pushToPropMap(
1945 aPropMap
, rFilterBase
.getGraphicHelper());
1946 PropertySet(xSet
).setProperties(aPropMap
);
1952 finalizeXShape( rFilterBase
, rxShapes
);
1956 // tdf#151518. The method readjustTextDistances is fix for tdf#148321, but conflicts with
1957 // text position in some of the SmartArt types in Writer. So exclude Writer here.
1958 OUString sDocumentService
;
1959 rFilterBase
.getMediaDescriptor()[utl::MediaDescriptor::PROP_DOCUMENTSERVICE
] >>= sDocumentService
;
1960 if (sDocumentService
!= u
"com.sun.star.text.TextDocument")
1961 mpTextBody
->getTextProperties().readjustTextDistances(mxShape
);
1967 void Shape::keepDiagramDrawing(XmlFilterBase
& rFilterBase
, const OUString
& rFragmentPath
)
1970 sal_Int32 length
= maDiagramDoms
.getLength();
1971 maDiagramDoms
.realloc(length
+ 1);
1973 // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships
1974 uno::Sequence
<uno::Any
> diagramDrawing
{
1975 uno::Any(rFilterBase
.importFragment(rFragmentPath
)),
1976 uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase
, rFragmentPath
, u
"image"))
1979 beans::PropertyValue
* pValue
= maDiagramDoms
.getArray();
1980 pValue
[length
].Name
= "OOXDrawing";
1981 pValue
[length
].Value
<<= diagramDrawing
;
1984 void Shape::keepDiagramCompatibilityInfo()
1988 if( !maDiagramDoms
.hasElements() )
1991 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY_THROW
);
1992 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
1993 if ( !xSetInfo
.is() )
1996 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
1997 if( !xSetInfo
->hasPropertyByName( aGrabBagPropName
) )
2000 Sequence
< PropertyValue
> aGrabBag
;
2001 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2003 // We keep the previous items, if present
2004 if ( aGrabBag
.hasElements() )
2005 xSet
->setPropertyValue( aGrabBagPropName
, Any( comphelper::concatSequences(aGrabBag
, maDiagramDoms
) ) );
2007 xSet
->setPropertyValue( aGrabBagPropName
, Any( maDiagramDoms
) );
2009 catch( const Exception
& )
2011 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::keepDiagramCompatibilityInfo" );
2015 void Shape::convertSmartArtToMetafile(XmlFilterBase
const & rFilterBase
)
2019 Reference
<XPropertySet
> xSet(mxShape
, UNO_QUERY_THROW
);
2021 xSet
->setPropertyValue("MoveProtect", Any(true));
2022 xSet
->setPropertyValue("SizeProtect", Any(true));
2024 // Replace existing shapes with a new Graphic Object rendered
2026 Reference
<XShape
> xShape(renderDiagramToGraphic(rFilterBase
));
2027 Reference
<XShapes
> xShapes(mxShape
, UNO_QUERY_THROW
);
2028 tools::Rectangle aBackgroundRect
2029 = SdrObject::getSdrObjectFromXShape(
2030 Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
))
2032 while (xShapes
->hasElements())
2033 xShapes
->remove(Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
));
2034 xShapes
->add(xShape
);
2035 SdrObject::getSdrObjectFromXShape(
2036 Reference
<XShape
>(xShapes
->getByIndex(0), UNO_QUERY_THROW
))
2037 ->NbcSetLogicRect(aBackgroundRect
);
2039 catch (const Exception
&)
2041 TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile");
2045 Reference
< XShape
> Shape::renderDiagramToGraphic( XmlFilterBase
const & rFilterBase
)
2047 Reference
< XShape
> xShape
;
2051 if( !maDiagramDoms
.hasElements() )
2054 // Stream in which to place the rendered shape
2055 SvMemoryStream aTempStream
;
2056 Reference
< io::XStream
> xStream( new utl::OStreamWrapper( aTempStream
) );
2057 Reference
< io::XOutputStream
> xOutputStream( xStream
->getOutputStream() );
2059 // Size of the rendering
2060 awt::Size aActualSize
= mxShape
->getSize();
2061 Size
aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM
)));
2062 double fPixelsPer100thmm
= static_cast < double > ( aResolution
.Width() ) / 100000.0;
2063 awt::Size
aSize( static_cast < sal_Int32
> ( ( fPixelsPer100thmm
* aActualSize
.Width
) + 0.5 ),
2064 static_cast < sal_Int32
> ( ( fPixelsPer100thmm
* aActualSize
.Height
) + 0.5 ) );
2066 Sequence
< PropertyValue
> aFilterData
{
2067 comphelper::makePropertyValue("PixelWidth", aSize
.Width
),
2068 comphelper::makePropertyValue("PixelHeight", aSize
.Height
),
2069 comphelper::makePropertyValue("LogicalWidth", aActualSize
.Width
),
2070 comphelper::makePropertyValue("LogicalHeight", aActualSize
.Height
)
2073 Sequence
< PropertyValue
> aDescriptor
{
2074 comphelper::makePropertyValue("OutputStream", xOutputStream
),
2075 comphelper::makePropertyValue("FilterName", OUString("SVM")), // Rendering format
2076 comphelper::makePropertyValue("FilterData", aFilterData
)
2079 Reference
< lang::XComponent
> xSourceDoc( mxShape
, UNO_QUERY_THROW
);
2080 Reference
< XGraphicExportFilter
> xGraphicExporter
= GraphicExportFilter::create( rFilterBase
.getComponentContext() );
2081 xGraphicExporter
->setSourceDocument( xSourceDoc
);
2082 xGraphicExporter
->filter( aDescriptor
);
2084 aTempStream
.Seek( STREAM_SEEK_TO_BEGIN
);
2087 GraphicFilter
aFilter( false );
2088 if ( aFilter
.ImportGraphic( aGraphic
, u
"", aTempStream
, GRFILTER_FORMAT_NOTFOUND
, nullptr, GraphicFilterImportFlags::NONE
) != ERRCODE_NONE
)
2090 SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" );
2094 Reference
< graphic::XGraphic
> xGraphic( aGraphic
.GetXGraphic() );
2095 Reference
< lang::XMultiServiceFactory
> xServiceFact( rFilterBase
.getModel(), UNO_QUERY_THROW
);
2096 xShape
.set( xServiceFact
->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), UNO_QUERY_THROW
);
2097 Reference
< XPropertySet
> xPropSet( xShape
, UNO_QUERY_THROW
);
2098 xPropSet
->setPropertyValue( "Graphic", Any( xGraphic
) );
2099 xPropSet
->setPropertyValue( "MoveProtect", Any( true ) );
2100 xPropSet
->setPropertyValue( "SizeProtect", Any( true ) );
2101 xPropSet
->setPropertyValue( "Name", Any( OUString( "RenderedShapes" ) ) );
2103 catch( const Exception
& )
2105 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" );
2111 void Shape::setTextBody(const TextBodyPtr
& pTextBody
)
2113 mpTextBody
= pTextBody
;
2116 void Shape::setMasterTextListStyle( const TextListStylePtr
& pMasterTextListStyle
)
2118 SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId
<< "'");
2120 mpMasterTextListStyle
= pMasterTextListStyle
;
2123 OUString
Shape::finalizeServiceName( XmlFilterBase
& rFilter
, const OUString
& rServiceName
, const awt::Rectangle
& rShapeRect
)
2125 OUString aServiceName
= rServiceName
;
2126 switch( meFrameType
)
2128 case FRAMETYPE_OLEOBJECT
:
2130 awt::Size
aOleSize( rShapeRect
.Width
, rShapeRect
.Height
);
2131 if( rFilter
.getOleObjectHelper().importOleObject( maShapeProperties
, *mxOleObjectInfo
, aOleSize
) )
2132 aServiceName
= "com.sun.star.drawing.OLE2Shape";
2134 // get the path to the representation graphic
2135 OUString aGraphicPath
;
2136 if( !mxOleObjectInfo
->maShapeId
.isEmpty() )
2137 if( ::oox::vml::Drawing
* pVmlDrawing
= rFilter
.getVmlDrawing() )
2138 if( const ::oox::vml::ShapeBase
* pVmlShape
= pVmlDrawing
->getShapes().getShapeById( mxOleObjectInfo
->maShapeId
) )
2139 aGraphicPath
= pVmlShape
->getGraphicPath();
2141 // import and store the graphic
2142 if( !aGraphicPath
.isEmpty() )
2144 // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF)
2145 WmfExternal aExtHeader
;
2146 aExtHeader
.mapMode
= 8; // MM_ANISOTROPIC
2147 aExtHeader
.xExt
= rShapeRect
.Width
;
2148 aExtHeader
.yExt
= rShapeRect
.Height
;
2150 Reference
< graphic::XGraphic
> xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic( aGraphicPath
, &aExtHeader
);
2152 maShapeProperties
.setProperty(PROP_Graphic
, xGraphic
);
2159 return aServiceName
;
2162 void Shape::finalizeXShape( XmlFilterBase
& rFilter
, const Reference
< XShapes
>& rxShapes
)
2164 switch( meFrameType
)
2166 case FRAMETYPE_CHART
:
2168 OSL_ENSURE( !mxChartShapeInfo
->maFragmentPath
.isEmpty(), "Shape::finalizeXShape - missing chart fragment" );
2169 if( mxShape
.is() && !mxChartShapeInfo
->maFragmentPath
.isEmpty() ) try
2171 // set the chart2 OLE class ID at the OLE shape
2172 PropertySet
aShapeProp( mxShape
);
2173 aShapeProp
.setProperty( PROP_CLSID
, OUString( "12dcae26-281f-416f-a234-c3086127382e" ) );
2175 // get the XModel interface of the embedded object from the OLE shape
2176 Reference
< frame::XModel
> xDocModel
;
2177 aShapeProp
.getProperty( xDocModel
, PROP_Model
);
2178 Reference
< chart2::XChartDocument
> xChartDoc( xDocModel
, UNO_QUERY_THROW
);
2180 // load the chart data from the XML fragment
2181 #if ENABLE_WASM_STRIP_CHART
2185 // WASM_CHART change
2186 // TODO: Instead of using convertFromModel an alternative may be
2187 // added to convert not to Chart/OLE SdrObejct, but to GraphicObject
2188 // with the Chart visualization. There should be a preview available
2189 // in the imported chart data
2190 bool bMSO2007Doc
= rFilter
.isMSO2007Document();
2191 chart::ChartSpaceModel
aModel(bMSO2007Doc
);
2192 oox::ppt::PowerPointImport
* pPowerPointImport
2193 = dynamic_cast<oox::ppt::PowerPointImport
*>(&rFilter
);
2195 ClrMapPtr pClrMap
; // The original color map
2196 if (pPowerPointImport
)
2198 // Use a copy of current color map, which the fragment may override locally
2199 pClrMap
= pPowerPointImport
->getActualSlidePersist()->getClrMap();
2200 aModel
.mpClrMap
= pClrMap
? std::make_shared
<ClrMap
>(*pClrMap
)
2201 : std::make_shared
<ClrMap
>();
2202 pPowerPointImport
->getActualSlidePersist()->setClrMap(aModel
.mpClrMap
);
2205 rtl::Reference
<chart::ChartSpaceFragment
> pChartSpaceFragment
= new chart::ChartSpaceFragment(
2206 rFilter
, mxChartShapeInfo
->maFragmentPath
, aModel
);
2207 const OUString
aThemeOverrideFragmentPath( pChartSpaceFragment
->
2208 getFragmentPathFromFirstTypeFromOfficeDoc(u
"themeOverride") );
2209 rFilter
.importFragment( pChartSpaceFragment
);
2211 // The original theme.
2214 if (!aThemeOverrideFragmentPath
.isEmpty() && pPowerPointImport
)
2216 // Handle theme override.
2217 uno::Reference
< xml::sax::XFastSAXSerializable
> xDoc(
2218 rFilter
.importFragment(aThemeOverrideFragmentPath
), uno::UNO_QUERY_THROW
);
2219 pTheme
= pPowerPointImport
->getActualSlidePersist()->getTheme();
2220 auto pThemeOverride
= std::make_shared
<Theme
>(*pTheme
);
2221 rFilter
.importFragment(
2222 new ThemeOverrideFragmentHandler(rFilter
, aThemeOverrideFragmentPath
, *pThemeOverride
, *pThemeOverride
->getTheme()),
2224 pPowerPointImport
->getActualSlidePersist()->setTheme(pThemeOverride
);
2227 // convert imported chart model to chart document
2228 Reference
< drawing::XShapes
> xExternalPage
;
2229 if( !mxChartShapeInfo
->mbEmbedShapes
)
2230 xExternalPage
= rxShapes
;
2231 if( rFilter
.getChartConverter() )
2233 rFilter
.getChartConverter()->convertFromModel( rFilter
, aModel
, xChartDoc
, xExternalPage
, mxShape
->getPosition(), mxShape
->getSize() );
2234 if( !xChartDoc
->hasInternalDataProvider() )
2236 Reference
< chart2::data::XDataReceiver
> xDataRec( xChartDoc
, UNO_QUERY
);
2237 Reference
< chart2::data::XDataSource
> xData
= xDataRec
->getUsedData();
2238 if( !xData
->getDataSequences().hasElements() || !xData
->getDataSequences()[0]->getValues().is() ||
2239 !xData
->getDataSequences()[0]->getValues()->getData().hasElements() )
2241 rFilter
.useInternalChartDataTable( true );
2242 rFilter
.getChartConverter()->convertFromModel( rFilter
, aModel
, xChartDoc
, xExternalPage
, mxShape
->getPosition(), mxShape
->getSize() );
2243 rFilter
.useInternalChartDataTable( false );
2249 if (pPowerPointImport
)
2251 if (!aThemeOverrideFragmentPath
.isEmpty())
2253 // Restore the original theme.
2254 pPowerPointImport
->getActualSlidePersist()->setTheme(pTheme
);
2256 // Restore the original color map
2257 pPowerPointImport
->getActualSlidePersist()->setClrMap(pClrMap
);
2271 void Shape::putPropertyToGrabBag( const OUString
& sPropertyName
, const Any
& aPropertyValue
)
2273 PropertyValue aNewProperty
;
2274 aNewProperty
.Name
= sPropertyName
;
2275 aNewProperty
.Value
= aPropertyValue
;
2276 putPropertyToGrabBag( aNewProperty
);
2279 void Shape::putPropertyToGrabBag( const PropertyValue
& pProperty
)
2281 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
2282 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
2283 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2284 if( mxShape
.is() && xSet
.is() && xSetInfo
.is() && xSetInfo
->hasPropertyByName( aGrabBagPropName
) )
2286 Sequence
< PropertyValue
> aGrabBag
;
2287 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2289 sal_Int32 length
= aGrabBag
.getLength();
2290 aGrabBag
.realloc( length
+ 1 );
2291 aGrabBag
.getArray()[length
] = pProperty
;
2293 xSet
->setPropertyValue( aGrabBagPropName
, Any( aGrabBag
) );
2297 void Shape::putPropertiesToGrabBag( const Sequence
< PropertyValue
>& aProperties
)
2299 Reference
< XPropertySet
> xSet( mxShape
, UNO_QUERY
);
2300 Reference
< XPropertySetInfo
> xSetInfo( xSet
->getPropertySetInfo() );
2301 const OUString aGrabBagPropName
= UNO_NAME_MISC_OBJ_INTEROPGRABBAG
;
2302 if( !(mxShape
.is() && xSet
.is() && xSetInfo
.is() && xSetInfo
->hasPropertyByName( aGrabBagPropName
)) )
2305 // get existing grab bag
2306 Sequence
< PropertyValue
> aGrabBag
;
2307 xSet
->getPropertyValue( aGrabBagPropName
) >>= aGrabBag
;
2309 std::vector
<PropertyValue
> aVec
;
2310 aVec
.reserve(aProperties
.getLength());
2312 // put the new items
2313 std::transform(aProperties
.begin(), aProperties
.end(), std::back_inserter(aVec
),
2314 [](const PropertyValue
& rProp
) {
2315 PropertyValue aProp
;
2316 aProp
.Name
= rProp
.Name
;
2317 aProp
.Value
= rProp
.Value
;
2321 // put it back to the shape
2322 xSet
->setPropertyValue( aGrabBagPropName
, Any( comphelper::concatSequences(aGrabBag
, aVec
) ) );
2325 FillProperties
Shape::getActualFillProperties(const Theme
* pTheme
, const FillProperties
* pParentShapeFillProps
) const
2327 FillProperties aFillProperties
;
2328 aFillProperties
.moFillType
= XML_noFill
;
2330 // Reference shape properties
2331 aFillProperties
.assignUsed( *mpShapeRefFillPropPtr
);
2334 if( pTheme
!= nullptr )
2336 if( const ShapeStyleRef
* pFillRef
= getShapeStyleRef( XML_fillRef
) )
2338 if( const FillProperties
* pFillProps
= pTheme
->getFillStyle( pFillRef
->mnThemedIdx
) )
2339 aFillProperties
.assignUsed( *pFillProps
);
2343 // Properties specified directly for this shape
2344 aFillProperties
.assignUsed(getFillProperties());
2346 // Parent shape's properties
2347 if ( pParentShapeFillProps
!= nullptr)
2348 if( getFillProperties().moFillType
.has_value() && getFillProperties().moFillType
.value() == XML_grpFill
)
2349 aFillProperties
.assignUsed( *pParentShapeFillProps
);
2351 return aFillProperties
;
2354 LineProperties
Shape::getActualLineProperties(const Theme
* pTheme
) const
2356 LineProperties aLineProperties
;
2357 aLineProperties
.maLineFill
.moFillType
= XML_noFill
;
2359 // Reference shape properties
2360 aLineProperties
.assignUsed( *mpShapeRefLinePropPtr
);
2363 if( pTheme
!= nullptr )
2365 if( const ShapeStyleRef
* pLineRef
= getShapeStyleRef( XML_lnRef
) )
2367 if( const LineProperties
* pLineProps
= pTheme
->getLineStyle( pLineRef
->mnThemedIdx
) )
2368 aLineProperties
.assignUsed( *pLineProps
);
2372 // Properties specified directly for this shape
2373 aLineProperties
.assignUsed( getLineProperties() );
2375 return aLineProperties
;
2378 EffectProperties
Shape::getActualEffectProperties(const Theme
* pTheme
) const
2380 EffectProperties aEffectProperties
;
2382 // Reference shape properties
2383 aEffectProperties
.assignUsed( *mpShapeRefEffectPropPtr
);
2386 if( pTheme
!= nullptr )
2388 if( const ShapeStyleRef
* pEffectRef
= getShapeStyleRef( XML_effectRef
) )
2390 if( const EffectProperties
* pEffectProps
= pTheme
->getEffectStyle( pEffectRef
->mnThemedIdx
) )
2391 aEffectProperties
.assignUsed( *pEffectProps
);
2395 // Properties specified directly for this shape
2396 aEffectProperties
.assignUsed ( getEffectProperties() );
2398 return aEffectProperties
;
2401 uno::Sequence
< uno::Sequence
< uno::Any
> > Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase
& rFilter
, const OUString
& sFragment
, std::u16string_view sType
)
2403 uno::Sequence
< uno::Sequence
< uno::Any
> > xRelListTemp
;
2404 sal_Int32 counter
= 0;
2406 core::RelationsRef xRels
= rFilter
.importRelations( sFragment
);
2409 core::RelationsRef xImageRels
= xRels
->getRelationsFromTypeFromOfficeDoc( sType
);
2412 xRelListTemp
.realloc( xImageRels
->size() );
2413 auto pxRelListTemp
= xRelListTemp
.getArray();
2414 for (auto const& imageRel
: *xImageRels
)
2416 uno::Sequence
< uno::Any
> diagramRelTuple (3);
2417 auto pdiagramRelTuple
= diagramRelTuple
.getArray();
2418 // [0] => RID, [1] => InputStream [2] => extension
2419 OUString sRelId
= imageRel
.second
.maId
;
2421 pdiagramRelTuple
[0] <<= sRelId
;
2422 OUString sTarget
= xImageRels
->getFragmentPathFromRelId( sRelId
);
2424 uno::Reference
< io::XInputStream
> xImageInputStrm( rFilter
.openInputStream( sTarget
), uno::UNO_SET_THROW
);
2425 StreamDataSequence dataSeq
;
2426 if ( rFilter
.importBinaryData( dataSeq
, sTarget
) )
2428 pdiagramRelTuple
[1] <<= dataSeq
;
2431 pdiagramRelTuple
[2] <<= sTarget
.copy( sTarget
.lastIndexOf(".") );
2433 pxRelListTemp
[counter
] = diagramRelTuple
;
2436 xRelListTemp
.realloc(counter
);
2440 return xRelListTemp
;
2443 void Shape::cloneFillProperties()
2445 auto pFillProperties
= std::make_shared
<FillProperties
>();
2446 pFillProperties
->assignUsed(*mpFillPropertiesPtr
);
2447 mpFillPropertiesPtr
= pFillProperties
;
2451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */