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 .
24 #include <o3tl/safeint.hxx>
25 #include <oox/vml/vmlshape.hxx>
27 #include <vcl/wmfexternal.hxx>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
31 #include <com/sun/star/drawing/FillStyle.hpp>
32 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
33 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
34 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
35 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
36 #include <com/sun/star/drawing/XShapes.hpp>
37 #include <com/sun/star/drawing/XControlShape.hpp>
38 #include <com/sun/star/graphic/XGraphic.hpp>
39 #include <com/sun/star/table/BorderLine2.hpp>
40 #include <com/sun/star/text/HoriOrientation.hpp>
41 #include <com/sun/star/text/RelOrientation.hpp>
42 #include <com/sun/star/text/SizeType.hpp>
43 #include <com/sun/star/text/VertOrientation.hpp>
44 #include <com/sun/star/text/WrapTextMode.hpp>
45 #include <com/sun/star/lang/XServiceInfo.hpp>
46 #include <com/sun/star/text/TextContentAnchorType.hpp>
47 #include <com/sun/star/text/GraphicCrop.hpp>
48 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
49 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
50 #include <com/sun/star/text/WritingMode2.hpp>
51 #include <com/sun/star/drawing/ColorMode.hpp>
52 #include <sal/log.hxx>
53 #include <oox/drawingml/shapepropertymap.hxx>
54 #include <oox/helper/graphichelper.hxx>
55 #include <oox/helper/propertyset.hxx>
56 #include <oox/ole/axcontrol.hxx>
57 #include <oox/ole/axcontrolfragment.hxx>
58 #include <oox/ole/oleobjecthelper.hxx>
59 #include <oox/token/properties.hxx>
60 #include <oox/token/tokens.hxx>
61 #include <oox/vml/vmldrawing.hxx>
62 #include <oox/vml/vmlshapecontainer.hxx>
63 #include <oox/vml/vmltextbox.hxx>
64 #include <oox/core/xmlfilterbase.hxx>
65 #include <oox/helper/containerhelper.hxx>
66 #include <svx/msdffdef.hxx>
67 #include <svx/sdtagitm.hxx>
68 #include <svx/svdobj.hxx>
69 #include <comphelper/sequence.hxx>
70 #include <comphelper/processfactory.hxx>
71 #include <comphelper/propertyvalue.hxx>
72 #include <comphelper/storagehelper.hxx>
73 #include <o3tl/string_view.hxx>
75 using ::com::sun::star::beans::XPropertySet
;
76 using ::com::sun::star::uno::Any
;
78 using namespace ::com::sun::star
;
79 using namespace ::com::sun::star::text
;
83 using namespace ::com::sun::star::drawing
;
84 using namespace ::com::sun::star::graphic
;
85 using namespace ::com::sun::star::uno
;
86 using namespace ::com::sun::star::io
;
88 using ::oox::core::XmlFilterBase
;
92 const sal_Int32 VML_SHAPETYPE_PICTUREFRAME
= 75;
93 const sal_Int32 VML_SHAPETYPE_HOSTCONTROL
= 201;
95 awt::Point
lclGetAbsPoint( const awt::Point
& rRelPoint
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
97 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
98 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
100 aAbsPoint
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelPoint
.X
- rCoordSys
.X
) + 0.5 );
101 aAbsPoint
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelPoint
.Y
- rCoordSys
.Y
) + 0.5 );
105 awt::Rectangle
lclGetAbsRect( const awt::Rectangle
& rRelRect
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
107 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
108 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
109 awt::Rectangle aAbsRect
;
110 aAbsRect
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelRect
.X
- rCoordSys
.X
) + 0.5 );
111 aAbsRect
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelRect
.Y
- rCoordSys
.Y
) + 0.5 );
112 aAbsRect
.Width
= static_cast< sal_Int32
>( fWidthRatio
* rRelRect
.Width
+ 0.5 );
113 aAbsRect
.Height
= static_cast< sal_Int32
>( fHeightRatio
* rRelRect
.Height
+ 0.5 );
117 /// Count the crop value based on a crop fraction and a reference size.
118 sal_Int32
lclConvertCrop(std::u16string_view rCrop
, sal_uInt32 nSize
)
120 if (o3tl::ends_with(rCrop
, u
"f"))
122 // Numeric value is specified in 1/65536-ths.
123 sal_uInt32 nCrop
= o3tl::toUInt32(rCrop
.substr(0, rCrop
.size() - 1));
124 return (nCrop
* nSize
) / 65536;
132 ShapeTypeModel::ShapeTypeModel():
133 mbAutoHeight( false ),
138 void ShapeTypeModel::assignUsed( const ShapeTypeModel
& rSource
)
140 assignIfUsed( moShapeType
, rSource
.moShapeType
);
141 assignIfUsed( moCoordPos
, rSource
.moCoordPos
);
142 assignIfUsed( moCoordSize
, rSource
.moCoordSize
);
143 /* The style properties position, left, top, width, height, margin-left,
144 margin-top are not derived from shape template to shape. */
145 maStrokeModel
.assignUsed( rSource
.maStrokeModel
);
146 maFillModel
.assignUsed( rSource
.maFillModel
);
147 assignIfUsed( moGraphicPath
, rSource
.moGraphicPath
);
148 assignIfUsed( moGraphicTitle
, rSource
.moGraphicTitle
);
151 ShapeType::ShapeType( Drawing
& rDrawing
) :
152 mrDrawing( rDrawing
)
157 ShapeType::~ShapeType()
161 sal_Int32
ShapeType::getShapeType() const
163 return maTypeModel
.moShapeType
.value_or( 0 );
166 OUString
ShapeType::getGraphicPath() const
168 return maTypeModel
.moGraphicPath
.value_or( OUString() );
171 awt::Rectangle
ShapeType::getCoordSystem() const
173 Int32Pair aCoordPos
= maTypeModel
.moCoordPos
.value_or( Int32Pair( 0, 0 ) );
174 Int32Pair aCoordSize
= maTypeModel
.moCoordSize
.value_or( Int32Pair( 1000, 1000 ) );
175 if( aCoordSize
.first
== 0 )
176 aCoordSize
.first
= 1;
177 if( aCoordSize
.second
== 0 )
178 aCoordSize
.second
= 1;
179 return awt::Rectangle( aCoordPos
.first
, aCoordPos
.second
, aCoordSize
.first
, aCoordSize
.second
);
182 awt::Rectangle
ShapeType::getRectangle( const ShapeParentAnchor
* pParentAnchor
) const
184 return pParentAnchor
?
185 lclGetAbsRect( getRelRectangle(), pParentAnchor
->maShapeRect
, pParentAnchor
->maCoordSys
) :
189 awt::Rectangle
ShapeType::getAbsRectangle() const
191 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
193 sal_Int32 nWidth
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maWidth
, 0, true, true );
197 sal_Int32 nHeight
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maHeight
, 0, false, true );
202 if (o3tl::checked_add
<sal_Int32
>(ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maLeft
, 0, true, true),
203 ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maMarginLeft
, 0, true, true),
206 SAL_WARN("oox", "overflow in addition");
209 if (nLeft
== 0 && maTypeModel
.maPosition
== "absolute")
213 if (o3tl::checked_add
<sal_Int32
>(ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maTop
, 0, false, true),
214 ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maMarginTop
, 0, false, true),
217 SAL_WARN("oox", "overflow in addition");
221 return awt::Rectangle(nLeft
, nTop
, nWidth
, nHeight
);
224 awt::Rectangle
ShapeType::getRelRectangle() const
226 sal_Int32 nWidth
= maTypeModel
.maWidth
.toInt32();
230 sal_Int32 nHeight
= maTypeModel
.maHeight
.toInt32();
234 return awt::Rectangle(
235 maTypeModel
.maLeft
.toInt32(),
236 maTypeModel
.maTop
.toInt32(),
240 ClientData::ClientData() :
241 mnObjType( XML_TOKEN_INVALID
),
242 mnTextHAlign( XML_Left
),
243 mnTextVAlign( XML_Top
),
246 mnChecked( VML_CLIENTDATA_UNCHECKED
),
247 mnDropStyle( XML_Combo
),
254 mnSelType( XML_Single
),
255 mnVTEdit( VML_CLIENTDATA_TEXT
),
256 mbPrintObject( true ),
261 mbMultiLine( false ),
263 mbSecretEdit( false )
267 ShapeModel::ShapeModel()
268 : mbIsSignatureLine(false)
269 , mbSignatureLineShowSignDate(true)
270 , mbSignatureLineCanAddComment(false)
275 ShapeModel::~ShapeModel()
279 TextBox
& ShapeModel::createTextBox(ShapeTypeModel
& rModel
)
281 mxTextBox
.reset( new TextBox(rModel
) );
285 ClientData
& ShapeModel::createClientData()
287 mxClientData
.reset( new ClientData
);
288 return *mxClientData
;
291 ShapeBase::ShapeBase( Drawing
& rDrawing
) :
292 ShapeType( rDrawing
)
296 void ShapeBase::finalizeFragmentImport()
298 if( maShapeModel
.maType
.getLength() <= 1 )
301 OUString aType
= maShapeModel
.maType
;
302 if (aType
[ 0 ] == '#')
303 aType
= aType
.copy(1);
304 if( const ShapeType
* pShapeType
= mrDrawing
.getShapes().getShapeTypeById( aType
) )
306 // Make sure that the props from maTypeModel have priority over the props from
308 StrokeModel aMergedStrokeModel
;
309 aMergedStrokeModel
.assignUsed(pShapeType
->getTypeModel().maStrokeModel
);
310 aMergedStrokeModel
.assignUsed(maTypeModel
.maStrokeModel
);
311 FillModel aMergedFillModel
;
312 aMergedFillModel
.assignUsed(pShapeType
->getTypeModel().maFillModel
);
313 aMergedFillModel
.assignUsed(maTypeModel
.maFillModel
);
315 maTypeModel
.assignUsed( pShapeType
->getTypeModel() );
316 maTypeModel
.maStrokeModel
= std::move(aMergedStrokeModel
);
317 maTypeModel
.maFillModel
= std::move(aMergedFillModel
);
320 // Temporary fix, shapetype not found if referenced from different substream
321 // FIXME: extend scope of ShapeContainer to store all shapetypes from the document
322 static constexpr OUString sShapeTypePrefix
= u
"shapetype_"_ustr
;
323 std::u16string_view tmp
;
324 if (aType
.startsWith(sShapeTypePrefix
)) {
325 maTypeModel
.moShapeType
= o3tl::toInt32(aType
.subView(sShapeTypePrefix
.getLength()));
327 else if (aType
.startsWith("_x0000_t", &tmp
)) {
328 maTypeModel
.moShapeType
= o3tl::toInt32(tmp
);
333 OUString
ShapeBase::getShapeName() const
335 if( !maTypeModel
.maShapeName
.isEmpty() )
336 return maTypeModel
.maShapeName
;
338 OUString aBaseName
= mrDrawing
.getShapeBaseName( *this );
339 if( !aBaseName
.isEmpty() )
341 sal_Int32 nShapeIdx
= mrDrawing
.getLocalShapeIndex( getShapeId() );
343 return aBaseName
+ OUStringChar(' ') + OUString::number( nShapeIdx
);
349 const ShapeType
* ShapeBase::getChildTypeById( const OUString
& ) const
354 const ShapeBase
* ShapeBase::getChildById( const OUString
& ) const
359 Reference
< XShape
> ShapeBase::convertAndInsert( const Reference
< XShapes
>& rxShapes
, const ShapeParentAnchor
* pParentAnchor
) const
361 Reference
< XShape
> xShape
;
362 if( mrDrawing
.isShapeSupported( *this ) )
364 /* Calculate shape rectangle. Applications may do something special
365 according to some imported shape client data (e.g. Excel cell anchor). */
366 awt::Rectangle aShapeRect
= calcShapeRectangle( pParentAnchor
);
368 if( ((aShapeRect
.Width
> 0) || (aShapeRect
.Height
> 0)) && rxShapes
.is() )
370 xShape
= implConvertAndInsert( rxShapes
, aShapeRect
);
373 // set imported or generated shape name (not supported by form controls)
374 PropertySet
aShapeProp( xShape
);
375 if( aShapeProp
.hasProperty( PROP_Name
) )
376 aShapeProp
.setProperty( PROP_Name
, getShapeName() );
377 uno::Reference
< lang::XServiceInfo
> xSInfo( xShape
, uno::UNO_QUERY_THROW
);
379 OUString sLinkChainName
= getTypeModel().maLegacyId
;
381 sal_Int32 idPos
= sLinkChainName
.indexOf("_x");
385 sal_Int32 seqPos
= sLinkChainName
.indexOf("_s",idPos
);
388 auto idPosEnd
= idPos
+2;
389 id
= o3tl::toInt32(sLinkChainName
.subView(idPosEnd
, seqPos
- idPosEnd
));
390 seq
= o3tl::toInt32(sLinkChainName
.subView(seqPos
+2));
394 OUString s_mso_next_textbox
;
396 s_mso_next_textbox
= getTextBox()->msNextTextbox
;
397 if( s_mso_next_textbox
.startsWith("#") )
398 s_mso_next_textbox
= s_mso_next_textbox
.copy(1);
400 if (xSInfo
->supportsService(u
"com.sun.star.text.TextFrame"_ustr
))
402 uno::Reference
<beans::XPropertySet
> propertySet (xShape
, uno::UNO_QUERY
);
403 uno::Any aAny
= propertySet
->getPropertyValue(u
"FrameInteropGrabBag"_ustr
);
404 auto aGrabBag
= comphelper::sequenceToContainer
< std::vector
<beans::PropertyValue
> >(aAny
.get
< uno::Sequence
<beans::PropertyValue
> >());
406 aGrabBag
.push_back(comphelper::makePropertyValue(u
"VML-Z-ORDER"_ustr
, maTypeModel
.maZIndex
.toInt32()));
408 if( !s_mso_next_textbox
.isEmpty() )
409 aGrabBag
.push_back(comphelper::makePropertyValue(u
"mso-next-textbox"_ustr
, s_mso_next_textbox
));
411 if( !sLinkChainName
.isEmpty() )
413 aGrabBag
.push_back(comphelper::makePropertyValue(u
"TxbxHasLink"_ustr
, true));
414 aGrabBag
.push_back(comphelper::makePropertyValue(u
"Txbx-Id"_ustr
, id
));
415 aGrabBag
.push_back(comphelper::makePropertyValue(u
"Txbx-Seq"_ustr
, seq
));
416 aGrabBag
.push_back(comphelper::makePropertyValue(u
"LinkChainName"_ustr
, sLinkChainName
));
419 if(!maTypeModel
.maRotation
.isEmpty())
420 aGrabBag
.push_back(comphelper::makePropertyValue(u
"mso-rotation-angle"_ustr
, ConversionHelper::decodeRotation(maTypeModel
.maRotation
).get()));
421 propertySet
->setPropertyValue(u
"FrameInteropGrabBag"_ustr
, uno::Any(comphelper::containerToSequence(aGrabBag
)));
422 sal_Int32 backColorTransparency
= 0;
423 propertySet
->getPropertyValue(u
"BackColorTransparency"_ustr
)
424 >>= backColorTransparency
;
425 if (propertySet
->getPropertyValue(u
"FillStyle"_ustr
) == FillStyle_NONE
&&
426 backColorTransparency
== 100)
428 // If there is no fill, the Word default is 100% transparency.
429 propertySet
->setPropertyValue(u
"FillTransparence"_ustr
, Any(sal_Int16(100)));
434 if( maTypeModel
.maZIndex
.toInt32() )
436 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
437 uno::Reference
<beans::XPropertySet
> propertySet (xShape
, uno::UNO_QUERY
);
438 propertySet
->getPropertyValue(u
"InteropGrabBag"_ustr
) >>= aGrabBag
;
441 length
= aGrabBag
.getLength();
442 aGrabBag
.realloc( length
+1 );
443 auto pGrabBag
= aGrabBag
.getArray();
444 pGrabBag
[length
].Name
= "VML-Z-ORDER";
445 pGrabBag
[length
].Value
<<= maTypeModel
.maZIndex
.toInt32();
447 if( !s_mso_next_textbox
.isEmpty() )
449 length
= aGrabBag
.getLength();
450 aGrabBag
.realloc( length
+1 );
451 pGrabBag
= aGrabBag
.getArray();
452 pGrabBag
[length
].Name
= "mso-next-textbox";
453 pGrabBag
[length
].Value
<<= s_mso_next_textbox
;
456 if( !sLinkChainName
.isEmpty() )
458 length
= aGrabBag
.getLength();
459 aGrabBag
.realloc( length
+4 );
460 pGrabBag
= aGrabBag
.getArray();
461 pGrabBag
[length
].Name
= "TxbxHasLink";
462 pGrabBag
[length
].Value
<<= true;
463 pGrabBag
[length
+1].Name
= "Txbx-Id";
464 pGrabBag
[length
+1].Value
<<= id
;
465 pGrabBag
[length
+2].Name
= "Txbx-Seq";
466 pGrabBag
[length
+2].Value
<<= seq
;
467 pGrabBag
[length
+3].Name
= "LinkChainName";
468 pGrabBag
[length
+3].Value
<<= sLinkChainName
;
470 propertySet
->setPropertyValue( u
"InteropGrabBag"_ustr
, uno::Any(aGrabBag
) );
473 Reference
< XControlShape
> xControlShape( xShape
, uno::UNO_QUERY
);
474 if ( xControlShape
.is() && !getTypeModel().mbVisible
)
476 PropertySet
aControlShapeProp( xControlShape
->getControl() );
477 aControlShapeProp
.setProperty( PROP_EnableVisible
, uno::Any( false ) );
480 xShape
= finalImplConvertAndInsert(xShape
);
481 /* Notify the drawing that a new shape has been inserted. For
482 convenience, pass the rectangle that contains position and
483 size of the shape. */
484 bool bGroupChild
= pParentAnchor
!= nullptr;
485 mrDrawing
.notifyXShapeInserted( xShape
, aShapeRect
, *this, bGroupChild
);
489 SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
494 awt::Rectangle
ShapeBase::getShapeRectangle() const
496 /* Calculate shape rectangle. Applications may do something special
497 according to some imported shape client data (e.g. Excel cell anchor). */
498 return calcShapeRectangle(nullptr);
501 void ShapeBase::setContainer(ShapeContainer
* pContainer
) { mpContainer
= pContainer
; }
503 ShapeContainer
* ShapeBase::getContainer() const { return mpContainer
; }
505 // protected ------------------------------------------------------------------
507 awt::Rectangle
ShapeBase::calcShapeRectangle( const ShapeParentAnchor
* pParentAnchor
) const
509 /* Calculate shape rectangle. Applications may do something special
510 according to some imported shape client data (e.g. Excel cell anchor). */
511 awt::Rectangle aShapeRect
;
512 const ClientData
* pClientData
= getClientData();
513 if( !pClientData
|| !mrDrawing
.convertClientAnchor( aShapeRect
, pClientData
->maAnchor
) )
514 aShapeRect
= getRectangle( pParentAnchor
);
518 ::oox::drawingml::ShapePropertyMap
ShapeBase::makeShapePropertyMap() const
520 ::oox::drawingml::ShapePropertyMap
aPropMap( mrDrawing
.getFilter().getModelObjectHelper() );
521 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
522 maTypeModel
.maStrokeModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
523 maTypeModel
.maFillModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
527 void ShapeBase::convertShapeProperties( const Reference
< XShape
>& rxShape
) const
529 ::oox::drawingml::ShapePropertyMap
aPropMap(makeShapePropertyMap());
531 uno::Reference
<lang::XServiceInfo
> xSInfo(rxShape
, uno::UNO_QUERY_THROW
);
532 if (xSInfo
->supportsService(u
"com.sun.star.text.TextFrame"_ustr
))
534 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
535 // Any other service supporting the ShadowFormat property?
536 maTypeModel
.maShadowModel
.pushToPropMap(aPropMap
, rGraphicHelper
);
537 // TextFrames have BackColor, not FillColor
538 if (aPropMap
.hasProperty(PROP_FillColor
))
540 aPropMap
.setAnyProperty(PROP_BackColor
, aPropMap
.getProperty(PROP_FillColor
));
541 aPropMap
.erase(PROP_FillColor
);
543 // TextFrames have BackColorTransparency, not FillTransparence
544 if (aPropMap
.hasProperty(PROP_FillTransparence
))
546 aPropMap
.setAnyProperty(PROP_BackColorTransparency
, aPropMap
.getProperty(PROP_FillTransparence
));
547 aPropMap
.erase(PROP_FillTransparence
);
549 // And no LineColor property; individual borders can have colors and widths
550 std::optional
<sal_Int32
> oLineWidth
;
551 if (maTypeModel
.maStrokeModel
.moWeight
.has_value())
552 oLineWidth
= ConversionHelper::decodeMeasureToHmm(
553 rGraphicHelper
, maTypeModel
.maStrokeModel
.moWeight
.value(), 0, false, false);
554 if (aPropMap
.hasProperty(PROP_LineColor
))
556 uno::Reference
<beans::XPropertySet
> xPropertySet(rxShape
, uno::UNO_QUERY
);
557 static const sal_Int32 aBorders
[] = {
558 PROP_TopBorder
, PROP_LeftBorder
, PROP_BottomBorder
, PROP_RightBorder
560 for (sal_Int32 nBorder
: aBorders
)
562 table::BorderLine2 aBorderLine
= xPropertySet
->getPropertyValue(PropertyMap::getPropertyName(nBorder
)).get
<table::BorderLine2
>();
563 aBorderLine
.Color
= aPropMap
.getProperty(PROP_LineColor
).get
<sal_Int32
>();
565 aBorderLine
.LineWidth
= *oLineWidth
;
566 aPropMap
.setProperty(nBorder
, aBorderLine
);
568 aPropMap
.erase(PROP_LineColor
);
571 else if (xSInfo
->supportsService(u
"com.sun.star.drawing.CustomShape"_ustr
))
573 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
574 maTypeModel
.maTextpathModel
.pushToPropMap(aPropMap
, rxShape
, rGraphicHelper
);
577 PropertySet( rxShape
).setProperties( aPropMap
);
580 SimpleShape::SimpleShape( Drawing
& rDrawing
, OUString aService
) :
581 ShapeBase( rDrawing
),
582 maService(std::move( aService
))
586 static void lcl_setSurround(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
, const GraphicHelper
& rGraphicHelper
)
588 OUString aWrapType
= rTypeModel
.moWrapType
.value_or("");
590 // Extreme negative top margin? Then the shape will end up at the top of the page, it's pointless to perform any kind of wrapping.
591 sal_Int32 nMarginTop
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, rTypeModel
.maMarginTop
, 0, false, true);
592 if (nMarginTop
< -35277) // Less than 1000 points.
595 css::text::WrapTextMode nSurround
= css::text::WrapTextMode_THROUGH
;
596 if ( aWrapType
== "square" || aWrapType
== "tight" ||
597 aWrapType
== "through" )
599 nSurround
= css::text::WrapTextMode_PARALLEL
;
600 if ( !rTypeModel
.moWrapSide
.has_value() )
601 ; // leave as PARALLEL
602 else if ( rTypeModel
.moWrapSide
.value() == "left" )
603 nSurround
= css::text::WrapTextMode_LEFT
;
604 else if ( rTypeModel
.moWrapSide
.value() == "right" )
605 nSurround
= css::text::WrapTextMode_RIGHT
;
607 else if ( aWrapType
== "topAndBottom" )
608 nSurround
= css::text::WrapTextMode_NONE
;
610 rPropSet
.setProperty(PROP_Surround
, static_cast<sal_Int32
>(nSurround
));
611 rPropSet
.setProperty(PROP_SurroundContour
, aWrapType
== "tight");
614 static void lcl_SetAnchorType(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
, const GraphicHelper
& rGraphicHelper
)
616 if ( rTypeModel
.maPosition
== "absolute" )
618 // Word supports as-character (inline) and at-character only, absolute can't be inline.
619 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_CHARACTER
);
620 // anchor is set after insertion, so reset to NONE
621 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::NONE
));
623 if ( rTypeModel
.maPositionVerticalRelative
== "page" )
625 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_FRAME
);
627 else if ( rTypeModel
.maPositionVerticalRelative
== "margin" )
629 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA
);
631 else if (rTypeModel
.maPositionVerticalRelative
== "top-margin-area")
633 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA_TOP
);
635 else if (rTypeModel
.maPositionVerticalRelative
== "bottom-margin-area")
637 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA_BOTTOM
);
641 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::FRAME
);
644 else if( rTypeModel
.maPosition
== "relative" )
645 { // I'm not very sure this is correct either.
646 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_PARAGRAPH
);
647 // anchor is set after insertion, so reset to NONE
648 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::NONE
));
650 else // static (is the default) means anchored inline
652 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AS_CHARACTER
);
653 // Use top orientation, this one seems similar to what MSO uses as inline
654 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::TOP
));
657 // if the anchor is not inline, and is relative to left or right, then apply the margins
658 bool bHonorMargins
= rTypeModel
.maPosition
== "relative" || rTypeModel
.maPosition
== "absolute";
659 if ( rTypeModel
.maPositionHorizontal
== "center" )
661 rPropSet
.setAnyProperty(PROP_HoriOrient
, Any(text::HoriOrientation::CENTER
));
662 bHonorMargins
= false;
664 else if ( rTypeModel
.maPositionHorizontal
== "left" )
665 rPropSet
.setAnyProperty(PROP_HoriOrient
, Any(text::HoriOrientation::LEFT
));
666 else if ( rTypeModel
.maPositionHorizontal
== "right" )
667 rPropSet
.setAnyProperty(PROP_HoriOrient
, Any(text::HoriOrientation::RIGHT
));
668 else if ( rTypeModel
.maPositionHorizontal
== "inside" )
670 rPropSet
.setAnyProperty(PROP_HoriOrient
, Any(text::HoriOrientation::LEFT
));
671 rPropSet
.setAnyProperty(PROP_PageToggle
, Any(true));
673 else if ( rTypeModel
.maPositionHorizontal
== "outside" )
675 rPropSet
.setAnyProperty(PROP_HoriOrient
, Any(text::HoriOrientation::RIGHT
));
676 rPropSet
.setAnyProperty(PROP_PageToggle
, Any(true));
679 bHonorMargins
= false;
681 if ( rTypeModel
.maPositionHorizontalRelative
== "page" )
682 rPropSet
.setAnyProperty(PROP_HoriOrientRelation
, Any(text::RelOrientation::PAGE_FRAME
));
683 else if ( rTypeModel
.maPositionHorizontalRelative
== "margin" )
684 rPropSet
.setProperty(PROP_HoriOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA
);
685 else if (rTypeModel
.maPositionHorizontalRelative
== "right-margin-area" ||
686 rTypeModel
.maPositionHorizontalRelative
== "inner-margin-area")
687 rPropSet
.setProperty(PROP_HoriOrientRelation
, text::RelOrientation::PAGE_RIGHT
);
688 else if (rTypeModel
.maPositionHorizontalRelative
== "left-margin-area" ||
689 rTypeModel
.maPositionHorizontalRelative
== "outer-margin-area")
690 rPropSet
.setProperty(PROP_HoriOrientRelation
, text::RelOrientation::PAGE_LEFT
);
694 rPropSet
.setProperty(PROP_HoriOrientRelation
, text::RelOrientation::PRINT_AREA
);
696 rPropSet
.setProperty(PROP_HoriOrientRelation
, text::RelOrientation::FRAME
);
698 if ( rTypeModel
.maPositionVertical
== "center" )
699 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::CENTER
));
700 else if ( rTypeModel
.maPositionVertical
== "top" )
701 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::TOP
));
702 else if ( rTypeModel
.maPositionVertical
== "bottom" )
703 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::BOTTOM
));
704 else if ( rTypeModel
.maPositionVertical
== "inside" )
705 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::TOP
));
706 else if ( rTypeModel
.maPositionVertical
== "outside" )
707 rPropSet
.setAnyProperty(PROP_VertOrient
, Any(text::VertOrientation::BOTTOM
));
709 lcl_setSurround( rPropSet
, rTypeModel
, rGraphicHelper
);
712 Reference
< XShape
> SimpleShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
714 awt::Rectangle
aShapeRect(rShapeRect
);
715 std::optional
<Degree100
> oRotation
;
716 bool bFlipX
= false, bFlipY
= false;
717 // tdf#137765: skip this rotation for line shapes
718 if (!maTypeModel
.maRotation
.isEmpty() && maService
!= "com.sun.star.drawing.LineShape")
719 oRotation
= ConversionHelper::decodeRotation(maTypeModel
.maRotation
);
720 if (!maTypeModel
.maFlip
.isEmpty())
722 if (maTypeModel
.maFlip
.startsWith("x"))
726 if (maTypeModel
.maFlip
.endsWith("y"))
732 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( maService
, rxShapes
, aShapeRect
);
733 SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(xShape
);
734 if( pShape
&& getShapeType() >= 0 )
736 //The resize autoshape to fit text attr of FontWork/Word-Art should always be false
737 //for the fallback geometry.
738 sal_Int32 nType
= getShapeType();
739 if((mso_sptTextSimple
<= nType
&& nType
<= mso_sptTextOnRing
)
740 || (mso_sptTextPlainText
<= nType
&& nType
<= mso_sptTextCanDown
))
742 pShape
->SetMergedItem(makeSdrTextAutoGrowHeightItem(false));
743 pShape
->SetMergedItem(makeSdrTextAutoGrowWidthItem(false));
746 convertShapeProperties( xShape
);
748 // Handle left/right/top/bottom wrap distance.
749 // Default value of mso-wrap-distance-left/right is supposed to be 0 (see
750 // 19.1.2.19 of the VML spec), but Word implements a non-zero value.
751 // [MS-ODRAW] says the below default value in 2.3.4.9.
752 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
753 OUString aWrapDistanceLeft
= OUString::number(0x0001BE7C);
754 if (!maTypeModel
.maWrapDistanceLeft
.isEmpty())
755 aWrapDistanceLeft
= maTypeModel
.maWrapDistanceLeft
;
756 sal_Int32 nWrapDistanceLeft
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, aWrapDistanceLeft
, 0, true, false);
757 PropertySet(xShape
).setAnyProperty(PROP_LeftMargin
, uno::Any(nWrapDistanceLeft
));
758 OUString aWrapDistanceRight
= OUString::number(0x0001BE7C);
759 if (!maTypeModel
.maWrapDistanceRight
.isEmpty())
760 aWrapDistanceRight
= maTypeModel
.maWrapDistanceRight
;
761 sal_Int32 nWrapDistanceRight
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, aWrapDistanceRight
, 0, true, false);
762 PropertySet(xShape
).setAnyProperty(PROP_RightMargin
, uno::Any(nWrapDistanceRight
));
763 sal_Int32 nWrapDistanceTop
= 0;
764 if (!maTypeModel
.maWrapDistanceTop
.isEmpty())
765 nWrapDistanceTop
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceTop
, 0, false, true);
766 PropertySet(xShape
).setAnyProperty(PROP_TopMargin
, uno::Any(nWrapDistanceTop
));
767 sal_Int32 nWrapDistanceBottom
= 0;
768 if (!maTypeModel
.maWrapDistanceBottom
.isEmpty())
769 nWrapDistanceBottom
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceBottom
, 0, false, true);
770 PropertySet(xShape
).setAnyProperty(PROP_BottomMargin
, uno::Any(nWrapDistanceBottom
));
772 if ( maService
== "com.sun.star.text.TextFrame" )
774 PropertySet( xShape
).setAnyProperty( PROP_FrameIsAutomaticHeight
, Any( maTypeModel
.mbAutoHeight
) );
775 PropertySet( xShape
).setAnyProperty( PROP_SizeType
, Any( maTypeModel
.mbAutoHeight
? SizeType::MIN
: SizeType::FIX
) );
776 if( getTextBox()->borderDistanceSet
)
778 PropertySet( xShape
).setAnyProperty( PROP_LeftBorderDistance
, Any( sal_Int32( getTextBox()->borderDistanceLeft
)));
779 PropertySet( xShape
).setAnyProperty( PROP_TopBorderDistance
, Any( sal_Int32( getTextBox()->borderDistanceTop
)));
780 PropertySet( xShape
).setAnyProperty( PROP_RightBorderDistance
, Any( sal_Int32( getTextBox()->borderDistanceRight
)));
781 PropertySet( xShape
).setAnyProperty( PROP_BottomBorderDistance
, Any( sal_Int32( getTextBox()->borderDistanceBottom
)));
784 sal_Int16 nWritingMode
= text::WritingMode2::LR_TB
;
785 if (getTextBox()->maLayoutFlow
== "vertical" && maTypeModel
.maLayoutFlowAlt
.isEmpty())
787 nWritingMode
= text::WritingMode2::TB_RL
;
789 else if (maTypeModel
.maLayoutFlowAlt
== "bottom-to-top")
791 nWritingMode
= text::WritingMode2::BT_LR
;
793 if (nWritingMode
!= text::WritingMode2::LR_TB
)
795 PropertySet(xShape
).setAnyProperty(PROP_WritingMode
, uno::Any(nWritingMode
));
798 if (!maShapeModel
.maHyperlink
.isEmpty())
799 PropertySet(xShape
).setAnyProperty(PROP_HyperLinkURL
, Any(maShapeModel
.maHyperlink
));
803 // FIXME Setting the relative width/height only for everything but text frames as
804 // TextFrames already have relative width/height feature... but currently not working
805 // in the way we need.
807 // Set the relative width / height if any
808 if ( !maTypeModel
.maWidthPercent
.isEmpty( ) )
810 // Only page-relative width is supported ATM
811 if ( maTypeModel
.maWidthRelative
.isEmpty() || maTypeModel
.maWidthRelative
== "page" )
813 sal_Int16 nWidth
= maTypeModel
.maWidthPercent
.toInt32() / 10;
814 // Only apply if nWidth != 0
816 PropertySet( xShape
).setAnyProperty(PROP_RelativeWidth
, Any( nWidth
) );
819 if ( !maTypeModel
.maHeightPercent
.isEmpty( ) )
821 // Only page-relative height is supported ATM
822 if ( maTypeModel
.maHeightRelative
.isEmpty() || maTypeModel
.maHeightRelative
== "page" )
824 sal_Int16 nHeight
= maTypeModel
.maHeightPercent
.toInt32() / 10;
825 // Only apply if nHeight != 0
827 PropertySet( xShape
).setAnyProperty(PROP_RelativeHeight
, Any( nHeight
) );
831 // drawinglayer default is center, MSO default is top.
832 drawing::TextVerticalAdjust eTextVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
833 if (maTypeModel
.maVTextAnchor
== "middle")
834 eTextVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
835 else if (maTypeModel
.maVTextAnchor
== "bottom")
836 eTextVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
837 PropertySet(xShape
).setAnyProperty(PROP_TextVerticalAdjust
, Any(eTextVerticalAdjust
));
840 const bool bWrap
= maTypeModel
.maWrapStyle
!= "none";
841 PropertySet(xShape
).setAnyProperty(PROP_TextWordWrap
, Any(bWrap
));
845 if (!maShapeModel
.maHyperlink
.isEmpty())
846 PropertySet(xShape
).setAnyProperty(PROP_Hyperlink
, Any(maShapeModel
.maHyperlink
));
848 PropertySet(xShape
).setAnyProperty(PROP_TextAutoGrowHeight
,
849 Any(maTypeModel
.mbAutoHeight
));
853 getTextBox()->convert(xShape
);
854 if (getTextBox()->borderDistanceSet
)
856 awt::Size aSize
= xShape
->getSize();
857 PropertySet(xShape
).setAnyProperty(PROP_TextLeftDistance
, Any(sal_Int32(getTextBox()->borderDistanceLeft
)));
858 PropertySet(xShape
).setAnyProperty(PROP_TextUpperDistance
, Any(sal_Int32(getTextBox()->borderDistanceTop
)));
859 PropertySet(xShape
).setAnyProperty(PROP_TextRightDistance
, Any(sal_Int32(getTextBox()->borderDistanceRight
)));
860 PropertySet(xShape
).setAnyProperty(PROP_TextLowerDistance
, Any(sal_Int32(getTextBox()->borderDistanceBottom
)));
861 xShape
->setSize(aSize
);
866 // similar to drawingml::Shape::createAndInsert(...)
867 PropertySet(xShape
).setAnyProperty(PROP_TextBox
, Any(true));
873 // Import Legacy Fragments (if any)
874 if( xShape
.is() && !maShapeModel
.maLegacyDiagramPath
.isEmpty() )
876 Reference
< XInputStream
> xInStrm( mrDrawing
.getFilter().openInputStream( maShapeModel
.maLegacyDiagramPath
), UNO_SET_THROW
);
878 PropertySet( xShape
).setProperty( PROP_LegacyFragment
, xInStrm
);
881 PropertySet
aPropertySet(xShape
);
886 aPropertySet
.setAnyProperty(PROP_RotateAngle
, Any((*oRotation
).get()));
887 uno::Reference
<lang::XServiceInfo
> xServiceInfo(rxShapes
, uno::UNO_QUERY
);
888 if (!xServiceInfo
->supportsService(u
"com.sun.star.drawing.GroupShape"_ustr
))
890 // If rotation is used, simple setPosition() is not enough.
891 aPropertySet
.setAnyProperty(PROP_HoriOrientPosition
, Any(aShapeRect
.X
));
892 aPropertySet
.setAnyProperty(PROP_VertOrientPosition
, Any(aShapeRect
.Y
));
895 if (!maTypeModel
.mbVisible
)
897 aPropertySet
.setAnyProperty(PROP_Visible
, uno::Any(false));
898 aPropertySet
.setAnyProperty(PROP_Printable
, uno::Any(false));
900 // custom shape geometry attributes
901 std::vector
<css::beans::PropertyValue
> aPropVec
;
903 // When flip has 'x' or 'y', the associated ShapeRect will be changed but direction change doesn't occur.
904 // It might occur internally in SdrObject of "sw" module, not here.
905 // The associated properties "PROP_MirroredX" and "PROP_MirroredY" have to be set here so that direction change will occur internally.
907 aPropVec
.push_back(comphelper::makePropertyValue(u
"MirroredX"_ustr
, true));
909 aPropVec
.push_back(comphelper::makePropertyValue(u
"MirroredY"_ustr
, true));
911 if (!maTypeModel
.maAdjustments
.isEmpty())
913 std::vector
<drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentValues
;
914 sal_Int32 nIndex
= 0;
917 std::u16string_view aToken
= o3tl::getToken(maTypeModel
.maAdjustments
, 0, ',', nIndex
);
918 drawing::EnhancedCustomShapeAdjustmentValue aAdjustmentValue
;
920 aAdjustmentValue
.State
= css::beans::PropertyState::PropertyState_DEFAULT_VALUE
;
922 aAdjustmentValue
.Value
<<= o3tl::toInt32(aToken
);
923 aAdjustmentValues
.push_back(aAdjustmentValue
);
924 } while (nIndex
>= 0);
926 css::beans::PropertyValue aProp
;
927 aProp
.Name
= "AdjustmentValues";
928 aProp
.Value
<<= comphelper::containerToSequence(aAdjustmentValues
);
929 aPropVec
.push_back(aProp
);
932 if (!aPropVec
.empty())
933 aPropertySet
.setAnyProperty(PROP_CustomShapeGeometry
, Any(comphelper::containerToSequence(aPropVec
)));
936 lcl_SetAnchorType(aPropertySet
, maTypeModel
, rGraphicHelper
);
941 Reference
<XShape
> SimpleShape::finalImplConvertAndInsert(const css::uno::Reference
<css::drawing::XShape
>& rxShape
) const
943 // tdf#41466 This setting must be done here, because the position of textbox will be set as an
944 // effect of the PROP_TextBox property setting, and if we do this setting earlier (setting of
945 // properties of position and size) then the position of textbox will be set with wrong data.
946 // TODO: TextShape is set if we have rect shape in group; we should use the shape-with-textbox
947 // mechanism to handle this situation
948 if (getTextBox() && maService
!= "com.sun.star.text.TextFrame" && maService
!= "com.sun.star.drawing.TextShape"
949 && !maShapeModel
.mbInGroup
)
951 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
952 const auto nLeft
= ConversionHelper::decodeMeasureToHmm(
953 rGraphicHelper
, maTypeModel
.maMarginLeft
, 0, true, true);
954 PropertySet
aPropertySet(rxShape
);
955 aPropertySet
.setProperty(PROP_HoriOrientPosition
, nLeft
);
956 const auto nTop
= ConversionHelper::decodeMeasureToHmm(
957 rGraphicHelper
, maTypeModel
.maMarginTop
, 0, true, true);
958 aPropertySet
.setProperty(PROP_VertOrientPosition
, nTop
);
959 aPropertySet
.setProperty(PROP_TextBox
, true);
961 // And these properties must be set after textbox creation (set PROP_Textbox property).
962 // Note: if you set a new property then you have to handle it in the proper
963 // SwTextBoxHelper::syncProperty function.
964 if (maTypeModel
.maLayoutFlowAlt
== "bottom-to-top")
965 aPropertySet
.setAnyProperty(PROP_TextWritingMode
, uno::Any(text::WritingMode2::BT_LR
));
967 return ShapeBase::finalImplConvertAndInsert(rxShape
);
969 Reference
< XShape
> SimpleShape::createEmbeddedPictureObject( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
, OUString
const & rGraphicPath
) const
971 Reference
<XGraphic
> xGraphic
= mrDrawing
.getFilter().getGraphicHelper().importEmbeddedGraphic(rGraphicPath
);
972 return SimpleShape::createPictureObject(rxShapes
, rShapeRect
, xGraphic
);
975 Reference
< XShape
> SimpleShape::createPictureObject(const Reference
< XShapes
>& rxShapes
,
976 const awt::Rectangle
& rShapeRect
,
977 uno::Reference
<graphic::XGraphic
> const & rxGraphic
) const
979 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( u
"com.sun.star.drawing.GraphicObjectShape"_ustr
, rxShapes
, rShapeRect
);
982 PropertySet
aPropSet(xShape
);
985 aPropSet
.setProperty(PROP_Graphic
, rxGraphic
);
987 uno::Reference
< lang::XServiceInfo
> xServiceInfo(rxShapes
, uno::UNO_QUERY
);
988 // If the shape has an absolute position, set the properties accordingly, unless we're inside a group shape.
989 if ( maTypeModel
.maPosition
== "absolute" && !xServiceInfo
->supportsService(u
"com.sun.star.drawing.GroupShape"_ustr
))
991 aPropSet
.setProperty(PROP_HoriOrientPosition
, rShapeRect
.X
);
992 aPropSet
.setProperty(PROP_VertOrientPosition
, rShapeRect
.Y
);
993 aPropSet
.setProperty(PROP_Opaque
, false);
995 // fdo#70457: preserve rotation information
996 if ( !maTypeModel
.maRotation
.isEmpty() )
997 aPropSet
.setAnyProperty(PROP_RotateAngle
, Any(ConversionHelper::decodeRotation(maTypeModel
.maRotation
).get()));
999 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1000 lcl_SetAnchorType(aPropSet
, maTypeModel
, rGraphicHelper
);
1002 const sal_Int32 nWrapDistanceLeft
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceLeft
, 0, true, true);
1003 const sal_Int32 nWrapDistanceRight
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceRight
, 0, true, true);
1004 const sal_Int32 nWrapDistanceTop
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceTop
, 0, false, true);
1005 const sal_Int32 nWrapDistanceBottom
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceBottom
, 0, false, true);
1006 aPropSet
.setProperty(PROP_LeftMargin
, uno::Any(nWrapDistanceLeft
));
1007 aPropSet
.setProperty(PROP_RightMargin
, uno::Any(nWrapDistanceRight
));
1008 aPropSet
.setProperty(PROP_TopMargin
, uno::Any(nWrapDistanceTop
));
1009 aPropSet
.setProperty(PROP_BottomMargin
, uno::Any(nWrapDistanceBottom
));
1011 if (maTypeModel
.moCropBottom
.has_value() || maTypeModel
.moCropLeft
.has_value() || maTypeModel
.moCropRight
.has_value() || maTypeModel
.moCropTop
.has_value())
1013 text::GraphicCrop aGraphicCrop
;
1014 awt::Size aOriginalSize
= rGraphicHelper
.getOriginalSize(rxGraphic
);
1016 if (maTypeModel
.moCropBottom
.has_value())
1017 aGraphicCrop
.Bottom
= lclConvertCrop(maTypeModel
.moCropBottom
.value(), aOriginalSize
.Height
);
1018 if (maTypeModel
.moCropLeft
.has_value())
1019 aGraphicCrop
.Left
= lclConvertCrop(maTypeModel
.moCropLeft
.value(), aOriginalSize
.Width
);
1020 if (maTypeModel
.moCropRight
.has_value())
1021 aGraphicCrop
.Right
= lclConvertCrop(maTypeModel
.moCropRight
.value(), aOriginalSize
.Width
);
1022 if (maTypeModel
.moCropTop
.has_value())
1023 aGraphicCrop
.Top
= lclConvertCrop(maTypeModel
.moCropTop
.value(), aOriginalSize
.Height
);
1025 aPropSet
.setProperty(PROP_GraphicCrop
, aGraphicCrop
);
1028 if (maTypeModel
.mnGain
== -70 && maTypeModel
.mnBlacklevel
== 70)
1030 // Map MSO 'washout' to our watermark colormode.
1031 aPropSet
.setProperty(PROP_GraphicColorMode
, uno::Any(drawing::ColorMode_WATERMARK
));
1037 RectangleShape::RectangleShape( Drawing
& rDrawing
) :
1038 SimpleShape( rDrawing
, u
"com.sun.star.drawing.RectangleShape"_ustr
)
1042 Reference
<XShape
> RectangleShape::implConvertAndInsert(const Reference
<XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1044 OUString aGraphicPath
= getGraphicPath();
1046 // try to create a picture object
1047 if(!aGraphicPath
.isEmpty())
1048 return SimpleShape::createEmbeddedPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
1050 // default: try to create a rectangle shape
1051 Reference
<XShape
> xShape
= SimpleShape::implConvertAndInsert(rxShapes
, rShapeRect
);
1052 OUString sArcsize
= maTypeModel
.maArcsize
;
1053 if ( !sArcsize
.isEmpty( ) )
1055 sal_Unicode cLastChar
= sArcsize
[sArcsize
.getLength() - 1];
1056 sal_Int32 nValue
= o3tl::toInt32(sArcsize
.subView( 0, sArcsize
.getLength() - 1 ));
1057 // Get the smallest half-side
1058 double size
= std::min( rShapeRect
.Height
, rShapeRect
.Width
) / 2.0;
1059 sal_Int32 nRadius
= 0;
1060 if ( cLastChar
== 'f' )
1061 nRadius
= size
* nValue
/ 65536;
1062 else if ( cLastChar
== '%' )
1063 nRadius
= size
* nValue
/ 100;
1064 PropertySet( xShape
).setAnyProperty( PROP_CornerRadius
, Any( nRadius
) );
1069 EllipseShape::EllipseShape( Drawing
& rDrawing
) :
1070 SimpleShape( rDrawing
, u
"com.sun.star.drawing.EllipseShape"_ustr
)
1074 PolyLineShape::PolyLineShape( Drawing
& rDrawing
) :
1075 SimpleShape( rDrawing
, u
"com.sun.star.drawing.PolyLineShape"_ustr
)
1079 Reference
< XShape
> PolyLineShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1081 ::std::vector
<awt::Point
> aAbsPoints
;
1082 awt::Rectangle aCoordSys
= getCoordSystem();
1083 if (!maShapeModel
.maPoints
.empty() && (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0))
1085 for (auto const& point
: maShapeModel
.maPoints
)
1086 aAbsPoints
.push_back(lclGetAbsPoint(point
, rShapeRect
, aCoordSys
));
1087 // A polyline cannot be filled but only a polygon. We treat first point == last point as
1088 // indicator for being closed. In that case we force to type PolyPolygonShape.
1089 if (aAbsPoints
.size() > 2 && aAbsPoints
.front().X
== aAbsPoints
.back().X
1090 && aAbsPoints
.front().Y
== aAbsPoints
.back().Y
)
1092 const_cast<PolyLineShape
*>(this)->setService(u
"com.sun.star.drawing.PolyPolygonShape"_ustr
);
1096 Reference
<XShape
> xShape
= SimpleShape::implConvertAndInsert(rxShapes
, rShapeRect
);
1100 if (!aAbsPoints
.empty())
1102 PointSequenceSequence aPointSeq
{ comphelper::containerToSequence( aAbsPoints
) };
1103 PropertySet
aPropSet( xShape
);
1104 aPropSet
.setProperty( PROP_PolyPolygon
, aPointSeq
);
1111 void doMirrorX(SdrObject
* pShape
)
1113 Point
aCenter(pShape
->GetSnapRect().Center());
1114 Point
aPoint2(aCenter
);
1115 aPoint2
.setY(aPoint2
.getY() + 1);
1116 pShape
->NbcMirror(aCenter
, aPoint2
);
1119 void doMirrorY(SdrObject
* pShape
)
1121 Point
aCenter(pShape
->GetSnapRect().Center());
1122 Point
aPoint2(aCenter
);
1123 aPoint2
.setX(aPoint2
.getX() + 1);
1124 pShape
->NbcMirror(aCenter
, aPoint2
);
1127 void handleMirroring(const ShapeTypeModel
& rTypeModel
, const Reference
<XShape
>& rxShape
)
1129 if (!rTypeModel
.maFlip
.isEmpty())
1131 if (SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(rxShape
))
1133 if (rTypeModel
.maFlip
.startsWith("x"))
1135 if (rTypeModel
.maFlip
.endsWith("y"))
1141 void handleRotation(const ShapeTypeModel
& rTypeModel
, const Reference
<XShape
>& rxShape
)
1143 if (!rTypeModel
.maRotation
.isEmpty())
1145 if (SdrObject
* pShape
= SdrObject::getSdrObjectFromXShape(rxShape
))
1147 // The needed factor -1 for opposite direction and factor 100 for Degree100 is
1148 // contained in method decodeRotation().
1149 Degree100
nAngle(ConversionHelper::decodeRotation(rTypeModel
.maRotation
));
1150 pShape
->NbcRotate(pShape
->GetSnapRect().Center(), nAngle
);
1156 LineShape::LineShape(Drawing
& rDrawing
)
1157 : SimpleShape(rDrawing
, u
"com.sun.star.drawing.LineShape"_ustr
)
1161 Reference
<XShape
> LineShape::implConvertAndInsert(const Reference
<XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1163 Reference
<XShape
> xShape
= SimpleShape::implConvertAndInsert(rxShapes
, rShapeRect
);
1165 handleRotation(maTypeModel
, xShape
);
1166 // tdf#97517 tdf#137678
1167 // The MirroredX and MirroredY properties (in the CustomShapeGeometry property) are not
1168 // supported for the LineShape by UNO, so we have to make the mirroring here.
1169 handleMirroring(maTypeModel
, xShape
);
1173 awt::Rectangle
LineShape::getAbsRectangle() const
1175 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1176 awt::Rectangle aShapeRect
;
1177 sal_Int32 nIndex
= 0;
1179 aShapeRect
.X
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
), 0, true, true);
1180 aShapeRect
.Y
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
), 0, false, true);
1182 aShapeRect
.Width
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
), 0, true, true) - aShapeRect
.X
;
1183 aShapeRect
.Height
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
), 0, false, true) - aShapeRect
.Y
;
1187 awt::Rectangle
LineShape::getRelRectangle() const
1189 awt::Rectangle aShapeRect
;
1190 sal_Int32 nIndex
= 0;
1192 aShapeRect
.X
= o3tl::toInt32(o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
));
1193 aShapeRect
.Y
= o3tl::toInt32(o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
));
1195 aShapeRect
.Width
= o3tl::toInt32(o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
)) - aShapeRect
.X
;
1196 aShapeRect
.Height
= o3tl::toInt32(o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
)) - aShapeRect
.Y
;
1200 BezierShape::BezierShape(Drawing
& rDrawing
)
1201 : SimpleShape(rDrawing
, u
"com.sun.star.drawing.OpenBezierShape"_ustr
)
1205 Reference
< XShape
> BezierShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1207 // If we have an 'x' in the last part of the path it means it is closed...
1208 sal_Int32 nPos
= maShapeModel
.maVmlPath
.lastIndexOf(',');
1209 if ( nPos
!= -1 && maShapeModel
.maVmlPath
.indexOf('x', nPos
) != -1 )
1211 const_cast<BezierShape
*>( this )->setService( u
"com.sun.star.drawing.ClosedBezierShape"_ustr
);
1214 awt::Rectangle aCoordSys
= getCoordSystem();
1215 PolyPolygonBezierCoords aBezierCoords
;
1217 if( (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0) )
1219 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1221 // Bezier paths may consist of one or more sub-paths
1222 typedef ::std::vector
< ::std::vector
< PolygonFlags
> > FlagsList
;
1223 std::vector
< ::std::vector
< awt::Point
> > aCoordLists
;
1224 FlagsList aFlagLists
;
1226 // Curve defined by to, from, control1 and control2 attributes
1227 if ( maShapeModel
.maVmlPath
.isEmpty() )
1229 aCoordLists
.emplace_back( );
1230 aFlagLists
.emplace_back( );
1231 sal_Int32 nIndex
= 0;
1234 aCoordLists
[ 0 ].emplace_back(
1235 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
), 0, true, true ),
1236 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maFrom
, 0, ',', nIndex
), 0, false, true ) );
1238 aCoordLists
[ 0 ].emplace_back(
1239 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maControl1
, 0, ',', nIndex
), 0, true, true ),
1240 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maControl1
, 0, ',', nIndex
), 0, false, true ) );
1242 aCoordLists
[ 0 ].emplace_back(
1243 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maControl2
, 0, ',', nIndex
), 0, true, true ),
1244 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maControl2
, 0, ',', nIndex
), 0, false, true ) );
1246 aCoordLists
[ 0 ].emplace_back(
1247 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
), 0, true, true ),
1248 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, o3tl::getToken(maShapeModel
.maTo
, 0, ',', nIndex
), 0, false, true ) );
1250 // First and last points are normals, points 2 and 4 are controls
1251 aFlagLists
[ 0 ].resize( aCoordLists
[ 0 ].size(), PolygonFlags_CONTROL
);
1252 aFlagLists
[ 0 ][ 0 ] = PolygonFlags_NORMAL
;
1253 aFlagLists
[ 0 ].back() = PolygonFlags_NORMAL
;
1255 // Curve defined by path attribute
1258 // Parse VML path string and convert to absolute coordinates
1259 ConversionHelper::decodeVmlPath( aCoordLists
, aFlagLists
, maShapeModel
.maVmlPath
);
1261 for (auto & coordList
: aCoordLists
)
1262 for (auto & point
: coordList
)
1264 point
= lclGetAbsPoint( point
, rShapeRect
, aCoordSys
);
1268 aBezierCoords
.Coordinates
.realloc( aCoordLists
.size() );
1269 auto pCoordinates
= aBezierCoords
.Coordinates
.getArray();
1270 for ( size_t i
= 0; i
< aCoordLists
.size(); i
++ )
1271 pCoordinates
[i
] = comphelper::containerToSequence( aCoordLists
[i
] );
1273 aBezierCoords
.Flags
.realloc( aFlagLists
.size() );
1274 auto pFlags
= aBezierCoords
.Flags
.getArray();
1275 for ( size_t i
= 0; i
< aFlagLists
.size(); i
++ )
1276 pFlags
[i
] = comphelper::containerToSequence( aFlagLists
[i
] );
1278 if( !aCoordLists
.front().empty() && !aCoordLists
.back().empty()
1279 && aCoordLists
.front().front().X
== aCoordLists
.back().back().X
1280 && aCoordLists
.front().front().Y
== aCoordLists
.back().back().Y
)
1281 { // HACK: If the shape is in fact closed, which can be found out only when the path is known,
1282 // force to closed bezier shape (otherwise e.g. fill won't work).
1283 const_cast< BezierShape
* >( this )->setService( u
"com.sun.star.drawing.ClosedBezierShape"_ustr
);
1287 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1289 if( aBezierCoords
.Coordinates
.hasElements())
1291 PropertySet
aPropSet( xShape
);
1292 aPropSet
.setProperty( PROP_PolyPolygonBezier
, aBezierCoords
);
1295 // tdf#105875 handle rotation
1296 // Note: must rotate before flip!
1297 handleRotation(maTypeModel
, xShape
);
1299 // Handle horizontal and vertical flip.
1300 handleMirroring(maTypeModel
, xShape
);
1305 CustomShape::CustomShape( Drawing
& rDrawing
) :
1306 SimpleShape( rDrawing
, u
"com.sun.star.drawing.CustomShape"_ustr
)
1310 Reference
< XShape
> CustomShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1312 // try to create a custom shape
1313 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1314 if( xShape
.is() ) try
1316 // create the custom shape geometry
1317 Reference
< XEnhancedCustomShapeDefaulter
> xDefaulter( xShape
, UNO_QUERY_THROW
);
1318 xDefaulter
->createCustomShapeDefaults( OUString::number( getShapeType() ) );
1319 // convert common properties
1320 convertShapeProperties( xShape
);
1328 ComplexShape::ComplexShape( Drawing
& rDrawing
) :
1329 CustomShape( rDrawing
)
1333 Reference
< XShape
> ComplexShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1335 XmlFilterBase
& rFilter
= mrDrawing
.getFilter();
1336 sal_Int32 nShapeType
= getShapeType();
1337 OUString aGraphicPath
= getGraphicPath();
1339 // try to find registered OLE object info
1340 if( const OleObjectInfo
* pOleObjectInfo
= mrDrawing
.getOleObjectInfo( maTypeModel
.maShapeId
) )
1343 nShapeType
!= VML_SHAPETYPE_PICTUREFRAME
, "oox",
1344 "ComplexShape::implConvertAndInsert - unexpected shape type");
1346 // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
1347 if( pOleObjectInfo
->mbDmlShape
)
1348 return Reference
< XShape
>();
1350 PropertyMap aOleProps
;
1351 awt::Size
aOleSize( rShapeRect
.Width
, rShapeRect
.Height
);
1352 if( rFilter
.getOleObjectHelper().importOleObject( aOleProps
, *pOleObjectInfo
, aOleSize
) )
1354 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( u
"com.sun.star.drawing.OLE2Shape"_ustr
, rxShapes
, rShapeRect
);
1357 // set the replacement graphic
1358 if( !aGraphicPath
.isEmpty() )
1360 WmfExternal aExtHeader
;
1361 aExtHeader
.mapMode
= 8;
1362 aExtHeader
.xExt
= rShapeRect
.Width
;
1363 aExtHeader
.yExt
= rShapeRect
.Height
;
1365 Reference
< XGraphic
> xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic(aGraphicPath
, &aExtHeader
);
1367 aOleProps
.setProperty( PROP_Graphic
, xGraphic
);
1370 PropertySet
aPropSet( xShape
);
1371 aPropSet
.setProperties( aOleProps
);
1378 // try to find registered form control info
1379 const ControlInfo
* pControlInfo
= mrDrawing
.getControlInfo( maTypeModel
.maShapeId
);
1380 if( pControlInfo
&& !pControlInfo
->maFragmentPath
.isEmpty() )
1382 if( !pControlInfo
->maName
.isEmpty() )
1384 // load the control properties from fragment
1385 ::oox::ole::EmbeddedControl
aControl(pControlInfo
->maName
);
1386 if( rFilter
.importFragment( new ::oox::ole::AxControlFragment( rFilter
, pControlInfo
->maFragmentPath
, aControl
) ) )
1388 // create and return the control shape (including control model)
1389 sal_Int32 nCtrlIndex
= -1;
1390 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXControlShape( aControl
, rxShapes
, rShapeRect
, nCtrlIndex
);
1392 if (pControlInfo
->mbTextContentShape
)
1394 PropertySet
aPropertySet(xShape
);
1395 lcl_SetAnchorType(aPropertySet
, maTypeModel
, mrDrawing
.getFilter().getGraphicHelper());
1397 // on error, proceed and try to create picture from replacement image
1404 // host application wants to create the shape (do not try failed OLE controls again)
1405 if( (nShapeType
== VML_SHAPETYPE_HOSTCONTROL
) && !pControlInfo
)
1407 OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
1408 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertClientXShape( *this, rxShapes
, rShapeRect
);
1414 if( getShapeModel().mbIsSignatureLine
)
1416 uno::Reference
<graphic::XGraphic
> xGraphic
;
1417 bool bIsSigned(false);
1420 // Get the document signatures
1421 Reference
<security::XDocumentDigitalSignatures
> xSignatures(
1422 security::DocumentDigitalSignatures::createDefault(
1423 comphelper::getProcessComponentContext()));
1425 uno::Reference
<embed::XStorage
> xStorage
1426 = comphelper::OStorageHelper::GetStorageOfFormatFromURL(
1427 ZIP_STORAGE_FORMAT_STRING
, mrDrawing
.getFilter().getFileUrl(),
1428 embed::ElementModes::READ
);
1429 SAL_WARN_IF(!xStorage
.is(), "oox.vml", "No xStorage!");
1431 const uno::Sequence
<security::DocumentSignatureInformation
> xSignatureInfo
1432 = xSignatures
->verifyScriptingContentSignatures(xStorage
,
1433 uno::Reference
<io::XInputStream
>());
1435 // Try to find matching signature line image - if none exists that is fine,
1436 // then the signature line is not digitally signed.
1437 auto pSignInfo
= std::find_if(xSignatureInfo
.begin(), xSignatureInfo
.end(),
1438 [this](const security::DocumentSignatureInformation
& rSigInfo
) {
1439 return rSigInfo
.SignatureLineId
== getShapeModel().maSignatureId
; });
1440 if (pSignInfo
!= xSignatureInfo
.end())
1443 if (pSignInfo
->SignatureIsValid
)
1445 // Signature is valid, use the 'valid' image
1446 SAL_WARN_IF(!pSignInfo
->ValidSignatureLineImage
.is(), "oox.vml",
1447 "No ValidSignatureLineImage!");
1448 xGraphic
= pSignInfo
->ValidSignatureLineImage
;
1452 // Signature is invalid, use the 'invalid' image
1453 SAL_WARN_IF(!pSignInfo
->InvalidSignatureLineImage
.is(), "oox.vml",
1454 "No InvalidSignatureLineImage!");
1455 xGraphic
= pSignInfo
->InvalidSignatureLineImage
;
1459 catch (css::uno::Exception
&)
1461 // DocumentDigitalSignatures service not available.
1462 // We continue by rendering the "unsigned" shape instead.
1465 Reference
< XShape
> xShape
;
1468 // If available, use the signed image from the signature
1469 xShape
= SimpleShape::createPictureObject(rxShapes
, rShapeRect
, xGraphic
);
1473 // Create shape with the fallback "unsigned" image
1474 xShape
= SimpleShape::createEmbeddedPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
1477 // Store signature line properties
1478 uno::Reference
<beans::XPropertySet
> xPropertySet(xShape
, uno::UNO_QUERY
);
1479 xPropertySet
->setPropertyValue(u
"IsSignatureLine"_ustr
, uno::Any(true));
1480 xPropertySet
->setPropertyValue(u
"SignatureLineId"_ustr
,
1481 uno::Any(getShapeModel().maSignatureId
));
1482 xPropertySet
->setPropertyValue(
1483 u
"SignatureLineSuggestedSignerName"_ustr
,
1484 uno::Any(getShapeModel().maSignatureLineSuggestedSignerName
));
1485 xPropertySet
->setPropertyValue(
1486 u
"SignatureLineSuggestedSignerTitle"_ustr
,
1487 uno::Any(getShapeModel().maSignatureLineSuggestedSignerTitle
));
1488 xPropertySet
->setPropertyValue(
1489 u
"SignatureLineSuggestedSignerEmail"_ustr
,
1490 uno::Any(getShapeModel().maSignatureLineSuggestedSignerEmail
));
1491 xPropertySet
->setPropertyValue(
1492 u
"SignatureLineSigningInstructions"_ustr
,
1493 uno::Any(getShapeModel().maSignatureLineSigningInstructions
));
1494 xPropertySet
->setPropertyValue(
1495 u
"SignatureLineShowSignDate"_ustr
,
1496 uno::Any(getShapeModel().mbSignatureLineShowSignDate
));
1497 xPropertySet
->setPropertyValue(
1498 u
"SignatureLineCanAddComment"_ustr
,
1499 uno::Any(getShapeModel().mbSignatureLineCanAddComment
));
1500 xPropertySet
->setPropertyValue(u
"SignatureLineIsSigned"_ustr
, uno::Any(bIsSigned
));
1502 if (!aGraphicPath
.isEmpty())
1504 xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic(aGraphicPath
);
1505 xPropertySet
->setPropertyValue(u
"SignatureLineUnsignedImage"_ustr
, uno::Any(xGraphic
));
1510 // try to create a picture object
1511 if( !aGraphicPath
.isEmpty() )
1513 Reference
<XShape
> xShape
= SimpleShape::createEmbeddedPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
1514 // AS_CHARACTER shape: vertical orientation default is bottom, MSO default is top.
1515 if ( maTypeModel
.maPosition
!= "absolute" && maTypeModel
.maPosition
!= "relative" )
1516 PropertySet( xShape
).setAnyProperty( PROP_VertOrient
, Any(text::VertOrientation::TOP
));
1518 // Apply stroke props from the type model.
1519 oox::drawingml::ShapePropertyMap
aPropMap(mrDrawing
.getFilter().getModelObjectHelper());
1520 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1521 maTypeModel
.maStrokeModel
.pushToPropMap(aPropMap
, rGraphicHelper
);
1522 // And, fill-color properties as well...
1523 maTypeModel
.maFillModel
.pushToPropMap(aPropMap
, rGraphicHelper
);
1524 PropertySet(xShape
).setProperties(aPropMap
);
1529 // default: try to create a custom shape
1530 return CustomShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1533 GroupShape::GroupShape( Drawing
& rDrawing
) :
1534 ShapeBase( rDrawing
),
1535 mxChildren( new ShapeContainer( rDrawing
) )
1539 GroupShape::~GroupShape()
1543 void GroupShape::finalizeFragmentImport()
1545 // basic shape processing
1546 ShapeBase::finalizeFragmentImport();
1547 // finalize all child shapes
1548 mxChildren
->finalizeFragmentImport();
1551 const ShapeType
* GroupShape::getChildTypeById( const OUString
& rShapeId
) const
1553 return mxChildren
->getShapeTypeById( rShapeId
);
1556 const ShapeBase
* GroupShape::getChildById( const OUString
& rShapeId
) const
1558 return mxChildren
->getShapeById( rShapeId
);
1561 Reference
< XShape
> GroupShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1563 Reference
< XShape
> xGroupShape
;
1564 // check that this shape contains children and a valid coordinate system
1565 ShapeParentAnchor aParentAnchor
;
1566 aParentAnchor
.maShapeRect
= rShapeRect
;
1567 aParentAnchor
.maCoordSys
= getCoordSystem();
1568 if( !mxChildren
->empty() && (aParentAnchor
.maCoordSys
.Width
> 0) && (aParentAnchor
.maCoordSys
.Height
> 0) ) try
1570 xGroupShape
= mrDrawing
.createAndInsertXShape( u
"com.sun.star.drawing.GroupShape"_ustr
, rxShapes
, rShapeRect
);
1571 Reference
< XShapes
> xChildShapes( xGroupShape
, UNO_QUERY_THROW
);
1572 mxChildren
->convertAndInsert( xChildShapes
, &aParentAnchor
);
1573 if( !xChildShapes
->hasElements() )
1575 SAL_WARN("oox", "no child shape has been created - deleting the group shape");
1576 rxShapes
->remove( xGroupShape
);
1577 xGroupShape
.clear();
1584 uno::Reference
<beans::XPropertySet
> xPropertySet
;
1585 if (!maTypeModel
.maEditAs
.isEmpty())
1586 xPropertySet
= uno::Reference
<beans::XPropertySet
>(xGroupShape
, uno::UNO_QUERY
);
1587 if (xPropertySet
.is())
1589 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1590 xPropertySet
->getPropertyValue(u
"InteropGrabBag"_ustr
) >>= aGrabBag
;
1591 sal_Int32 nLength
= aGrabBag
.getLength();
1592 aGrabBag
.realloc(nLength
+ 1);
1593 aGrabBag
.getArray()[nLength
] = comphelper::makePropertyValue(u
"mso-edit-as"_ustr
, maTypeModel
.maEditAs
);
1594 xPropertySet
->setPropertyValue(u
"InteropGrabBag"_ustr
, uno::Any(aGrabBag
));
1596 // Make sure group shapes are inline as well, unless there is an explicit different style.
1597 PropertySet
aPropertySet(xGroupShape
);
1598 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1599 lcl_SetAnchorType(aPropertySet
, maTypeModel
, rGraphicHelper
);
1600 if (!maTypeModel
.maRotation
.isEmpty())
1601 aPropertySet
.setAnyProperty(PROP_RotateAngle
, Any(ConversionHelper::decodeRotation(maTypeModel
.maRotation
).get()));
1607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */