Gtk-WARNING gtktreestore.c:1047: Invalid column number 1 added to iter
[LibreOffice.git] / oox / source / vml / vmlshape.cxx
blob7908dd7527c45993ec4489e9abe2d2ab64378bb8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <algorithm>
22 #include <optional>
24 #include <o3tl/safeint.hxx>
25 #include <oox/vml/vmlshape.hxx>
26 #include <utility>
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;
81 namespace oox::vml {
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;
90 namespace {
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;
99 awt::Point aAbsPoint;
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 );
102 return aAbsPoint;
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 );
114 return aAbsRect;
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;
127 return 0;
130 } // namespace
132 ShapeTypeModel::ShapeTypeModel():
133 mbAutoHeight( false ),
134 mbVisible( true )
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 )
153 , mbTextBox(false)
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 ) :
186 getAbsRectangle();
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 );
194 if ( nWidth == 0 )
195 nWidth = 1;
197 sal_Int32 nHeight = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true );
198 if ( nHeight == 0 )
199 nHeight = 1;
201 sal_Int32 nLeft;
202 if (o3tl::checked_add<sal_Int32>(ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maLeft, 0, true, true),
203 ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true),
204 nLeft))
206 SAL_WARN("oox", "overflow in addition");
207 nLeft = 0;
209 if (nLeft == 0 && maTypeModel.maPosition == "absolute")
210 nLeft = 1;
212 sal_Int32 nTop;
213 if (o3tl::checked_add<sal_Int32>(ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maTop, 0, false, true),
214 ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maMarginTop, 0, false, true),
215 nTop))
217 SAL_WARN("oox", "overflow in addition");
218 nTop = 0;
221 return awt::Rectangle(nLeft, nTop, nWidth, nHeight);
224 awt::Rectangle ShapeType::getRelRectangle() const
226 sal_Int32 nWidth = maTypeModel.maWidth.toInt32();
227 if ( nWidth == 0 )
228 nWidth = 1;
230 sal_Int32 nHeight = maTypeModel.maHeight.toInt32();
231 if ( nHeight == 0 )
232 nHeight = 1;
234 return awt::Rectangle(
235 maTypeModel.maLeft.toInt32(),
236 maTypeModel.maTop.toInt32(),
237 nWidth, nHeight );
240 ClientData::ClientData() :
241 mnObjType( XML_TOKEN_INVALID ),
242 mnTextHAlign( XML_Left ),
243 mnTextVAlign( XML_Top ),
244 mnCol( -1 ),
245 mnRow( -1 ),
246 mnChecked( VML_CLIENTDATA_UNCHECKED ),
247 mnDropStyle( XML_Combo ),
248 mnDropLines( 1 ),
249 mnVal( 0 ),
250 mnMin( 0 ),
251 mnMax( 0 ),
252 mnInc( 0 ),
253 mnPage( 0 ),
254 mnSelType( XML_Single ),
255 mnVTEdit( VML_CLIENTDATA_TEXT ),
256 mbPrintObject( true ),
257 mbVisible( false ),
258 mbDde( false ),
259 mbNo3D( false ),
260 mbNo3D2( false ),
261 mbMultiLine( false ),
262 mbVScroll( false ),
263 mbSecretEdit( false )
267 ShapeModel::ShapeModel()
268 : mbIsSignatureLine(false)
269 , mbSignatureLineShowSignDate(true)
270 , mbSignatureLineCanAddComment(false)
271 , mbInGroup(false)
275 ShapeModel::~ShapeModel()
279 TextBox& ShapeModel::createTextBox(ShapeTypeModel& rModel)
281 mxTextBox.reset( new TextBox(rModel) );
282 return *mxTextBox;
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 )
299 return;
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
307 // the shape type.
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);
319 else {
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() );
342 if( nShapeIdx > 0 )
343 return aBaseName + OUStringChar(' ') + OUString::number( nShapeIdx );
346 return OUString();
349 const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
351 return nullptr;
354 const ShapeBase* ShapeBase::getChildById( const OUString& ) const
356 return nullptr;
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 );
371 if( xShape.is() )
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;
380 sal_Int32 id = 0;
381 sal_Int32 idPos = sLinkChainName.indexOf("_x");
382 sal_Int32 seq = 0;
383 if (idPos >= 0)
385 sal_Int32 seqPos = sLinkChainName.indexOf("_s",idPos);
386 if (idPos < seqPos)
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;
395 if( getTextBox() )
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)));
432 else
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;
439 sal_Int32 length;
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 );
488 else
489 SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
491 return xShape;
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 );
515 return aShapeRect;
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 );
524 return aPropMap;
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>();
564 if (oLineWidth)
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.
593 aWrapType.clear();
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);
639 else
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));
678 else
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);
691 else // "text"
693 if (bHonorMargins)
694 rPropSet.setProperty(PROP_HoriOrientRelation, text::RelOrientation::PRINT_AREA);
695 else
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"))
724 bFlipX = true;
726 if (maTypeModel.maFlip.endsWith("y"))
728 bFlipY = true;
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));
797 // tdf#123626
798 if (!maShapeModel.maHyperlink.isEmpty())
799 PropertySet(xShape).setAnyProperty(PROP_HyperLinkURL, Any(maShapeModel.maHyperlink));
801 else
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
815 if ( nWidth )
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
826 if ( nHeight )
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));
839 // tdf#97618
840 const bool bWrap = maTypeModel.maWrapStyle != "none";
841 PropertySet(xShape).setAnyProperty(PROP_TextWordWrap, Any(bWrap));
844 // tdf#123626
845 if (!maShapeModel.maHyperlink.isEmpty())
846 PropertySet(xShape).setAnyProperty(PROP_Hyperlink, Any(maShapeModel.maHyperlink));
848 PropertySet(xShape).setAnyProperty(PROP_TextAutoGrowHeight,
849 Any(maTypeModel.mbAutoHeight));
851 if (getTextBox())
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);
864 if (mbTextBox)
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 );
877 if( xInStrm.is() )
878 PropertySet( xShape ).setProperty( PROP_LegacyFragment, xInStrm );
881 PropertySet aPropertySet(xShape);
882 if (xShape.is())
884 if (oRotation)
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.
906 if (bFlipX)
907 aPropVec.push_back(comphelper::makePropertyValue(u"MirroredX"_ustr, true));
908 if (bFlipY)
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;
919 if (aToken.empty())
920 aAdjustmentValue.State = css::beans::PropertyState::PropertyState_DEFAULT_VALUE;
921 else
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 );
938 return xShape;
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 );
980 if( xShape.is() )
982 PropertySet aPropSet(xShape);
983 if (rxGraphic.is())
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));
1034 return xShape;
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 ) );
1066 return xShape;
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);
1098 // polygon path
1100 if (!aAbsPoints.empty())
1102 PointSequenceSequence aPointSeq{ comphelper::containerToSequence( aAbsPoints ) };
1103 PropertySet aPropSet( xShape );
1104 aPropSet.setProperty( PROP_PolyPolygon, aPointSeq );
1106 return xShape;
1109 namespace
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"))
1134 doMirrorX(pShape);
1135 if (rTypeModel.maFlip.endsWith("y"))
1136 doMirrorY(pShape);
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);
1164 // tdf#137765
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);
1170 return 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);
1181 nIndex = 0;
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;
1184 return aShapeRect;
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));
1194 nIndex = 0;
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;
1197 return aShapeRect;
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;
1233 // Start point
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 ) );
1237 // Control point 1
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 ) );
1241 // Control point 2
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 ) );
1245 // End point
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
1256 else
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);
1302 return 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 );
1322 catch( Exception& )
1325 return 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 ) )
1342 SAL_WARN_IF(
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 );
1355 if( xShape.is() )
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);
1366 if (xGraphic.is())
1367 aOleProps.setProperty( PROP_Graphic, xGraphic);
1370 PropertySet aPropSet( xShape );
1371 aPropSet.setProperties( aOleProps );
1373 return xShape;
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
1398 if( xShape.is() )
1399 return xShape;
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 );
1409 if( xShape.is() )
1410 return xShape;
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())
1442 bIsSigned = true;
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;
1450 else
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;
1466 if (xGraphic.is())
1468 // If available, use the signed image from the signature
1469 xShape = SimpleShape::createPictureObject(rxShapes, rShapeRect, xGraphic);
1471 else
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));
1507 return xShape;
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);
1526 return xShape;
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();
1580 catch( Exception& )
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()));
1602 return xGroupShape;
1605 } // namespace oox
1607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */