1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <oox/drawingml/shape.hxx> 21 #include <drawingml/customshapeproperties.hxx> 22 #include <oox/drawingml/theme.hxx> 23 #include <drawingml/fillproperties.hxx> 24 #include <drawingml/graphicproperties.hxx> 25 #include <drawingml/lineproperties.hxx> 26 #include <drawingml/presetgeometrynames.hxx> 27 #include <drawingml/shape3dproperties.hxx> 28 #include "effectproperties.hxx" 29 #include <oox/drawingml/shapepropertymap.hxx> 30 #include <drawingml/textbody.hxx> 31 #include <drawingml/textparagraph.hxx> 32 #include <drawingml/ThemeOverrideFragmentHandler.hxx> 33 #include <drawingml/table/tableproperties.hxx> 34 #include <oox/drawingml/chart/chartconverter.hxx> 35 #include <drawingml/chart/chartspacefragment.hxx> 36 #include <drawingml/chart/chartspacemodel.hxx> 37 #include <o3tl/safeint.hxx> 38 #include <oox/ppt/pptimport.hxx> 39 #include <oox/vml/vmldrawing.hxx> 40 #include <oox/vml/vmlshape.hxx> 41 #include <oox/vml/vmlshapecontainer.hxx> 42 #include <oox/core/xmlfilterbase.hxx> 43 #include <oox/helper/graphichelper.hxx> 44 #include <oox/helper/propertyset.hxx> 45 #include <oox/helper/modelobjecthelper.hxx> 46 #include <oox/mathml/importutils.hxx> 47 #include <oox/mathml/import.hxx> 48 #include <oox/token/properties.hxx> 49 #include "diagram/datamodel.hxx" 50 51 #include <comphelper/classids.hxx> 52 #include <comphelper/propertysequence.hxx> 53 #include <comphelper/propertyvalue.hxx> 54 #include <comphelper/sequence.hxx> 55 #include <tools/diagnose_ex.h> 56 #include <tools/gen.hxx> 57 #include <tools/globname.hxx> 58 #include <tools/mapunit.hxx> 59 #include <editeng/unoprnms.hxx> 60 #include <com/sun/star/awt/Size.hpp> 61 #include <com/sun/star/awt/XBitmap.hpp> 62 #include <com/sun/star/awt/FontWeight.hpp> 63 #include <com/sun/star/graphic/XGraphic.hpp> 64 #include <com/sun/star/container/XNamed.hpp> 65 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 66 #include <com/sun/star/xml/dom/XDocument.hpp> 67 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> 68 #include <com/sun/star/drawing/FillStyle.hpp> 69 #include <com/sun/star/drawing/HomogenMatrix3.hpp> 70 #include <com/sun/star/drawing/TextVerticalAdjust.hpp> 71 #include <com/sun/star/drawing/GraphicExportFilter.hpp> 72 #include <com/sun/star/drawing/XShapes.hpp> 73 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp> 74 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp> 75 #include <com/sun/star/embed/XEmbeddedObject.hpp> 76 #include <com/sun/star/text/XText.hpp> 77 #include <com/sun/star/table/BorderLine2.hpp> 78 #include <com/sun/star/table/ShadowFormat.hpp> 79 #include <com/sun/star/chart2/XChartDocument.hpp> 80 #include <com/sun/star/style/ParagraphAdjust.hpp> 81 #include <com/sun/star/io/XOutputStream.hpp> 82 83 #include <basegfx/point/b2dpoint.hxx> 84 #include <basegfx/polygon/b2dpolygon.hxx> 85 #include <basegfx/matrix/b2dhommatrix.hxx> 86 #include <com/sun/star/document/XActionLockable.hpp> 87 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 88 #include <svx/svdtrans.hxx> 89 #include <tools/stream.hxx> 90 #include <unotools/streamwrap.hxx> 91 #include <unotools/fltrcfg.hxx> 92 #include <vcl/graph.hxx> 93 #include <vcl/graphicfilter.hxx> 94 #include <vcl/svapp.hxx> 95 #include <vcl/wmfexternal.hxx> 96 #include <sal/log.hxx> 97 #include <svx/unoapi.hxx> 98 #include <svx/unoshape.hxx> 99 #include <svx/sdtaitm.hxx> 100 101 using namespace ::oox::core; 102 using namespace ::com::sun::star; 103 using namespace ::com::sun::star::uno; 104 using namespace ::com::sun::star::beans; 105 using namespace ::com::sun::star::frame; 106 using namespace ::com::sun::star::text; 107 using namespace ::com::sun::star::drawing; 108 using namespace ::com::sun::star::style; 109 110 namespace oox::drawingml { 111 112 Shape::Shape( const char* pServiceName, bool bDefaultHeight ) 113 : mpLinePropertiesPtr( std::make_shared<LineProperties>() ) 114 , mpShapeRefLinePropPtr( std::make_shared<LineProperties>() ) 115 , mpFillPropertiesPtr( std::make_shared<FillProperties>() ) 116 , mpShapeRefFillPropPtr( std::make_shared<FillProperties>() ) 117 , mpGraphicPropertiesPtr( std::make_shared<GraphicProperties>() ) 118 , mpCustomShapePropertiesPtr( std::make_shared<CustomShapeProperties>() ) 119 , mp3DPropertiesPtr( std::make_shared<Shape3DProperties>() ) 120 , mpEffectPropertiesPtr( std::make_shared<EffectProperties>() ) 121 , mpShapeRefEffectPropPtr( std::make_shared<EffectProperties>() ) 122 , mpMasterTextListStyle( std::make_shared<TextListStyle>() ) 123 , mnSubType( 0 ) 124 , meFrameType( FRAMETYPE_GENERIC ) 125 , mnRotation( 0 ) 126 , mnDiagramRotation( 0 ) 127 , mbFlipH( false ) 128 , mbFlipV( false ) 129 , mbHidden( false ) 130 , mbHiddenMasterShape( false ) 131 , mbLocked( false ) 132 , mbLockedCanvas( false ) 133 , mbWps( false ) 134 , mbTextBox( false ) 135 , mbHasLinkedTxbx( false ) 136 , maDiagramDoms( 0 ) 137 { 138 if ( pServiceName ) 139 msServiceName = OUString::createFromAscii( pServiceName ); 140 setDefaults(bDefaultHeight); 141 } 142 143 Shape::Shape( const ShapePtr& pSourceShape ) 144 : maChildren() 145 , mpTextBody(pSourceShape->mpTextBody) 146 , mpLinePropertiesPtr( pSourceShape->mpLinePropertiesPtr ) 147 , mpShapeRefLinePropPtr( pSourceShape->mpShapeRefLinePropPtr ) 148 , mpFillPropertiesPtr( pSourceShape->mpFillPropertiesPtr ) 149 , mpShapeRefFillPropPtr( pSourceShape->mpShapeRefFillPropPtr ) 150 , mpGraphicPropertiesPtr( pSourceShape->mpGraphicPropertiesPtr ) 151 , mpCustomShapePropertiesPtr( pSourceShape->mpCustomShapePropertiesPtr ) 152 , mpTablePropertiesPtr( pSourceShape->mpTablePropertiesPtr ) 153 , mp3DPropertiesPtr( pSourceShape->mp3DPropertiesPtr ) 154 , mpEffectPropertiesPtr (pSourceShape->mpEffectPropertiesPtr) 155 , mpShapeRefEffectPropPtr(pSourceShape->mpShapeRefEffectPropPtr) 156 , maShapeProperties( pSourceShape->maShapeProperties ) 157 , mpMasterTextListStyle( pSourceShape->mpMasterTextListStyle ) 158 , mxShape() 159 , msServiceName( pSourceShape->msServiceName ) 160 , msName( pSourceShape->msName ) 161 , msInternalName( pSourceShape->msInternalName ) 162 , msId( pSourceShape->msId ) 163 , mnSubType( pSourceShape->mnSubType ) 164 , moSubTypeIndex( pSourceShape->moSubTypeIndex ) 165 , maShapeStyleRefs( pSourceShape->maShapeStyleRefs ) 166 , maSize( pSourceShape->maSize ) 167 , maPosition( pSourceShape->maPosition ) 168 , meFrameType( pSourceShape->meFrameType ) 169 , mnRotation( pSourceShape->mnRotation ) 170 , mnDiagramRotation( pSourceShape->mnDiagramRotation ) 171 , mbFlipH( pSourceShape->mbFlipH ) 172 , mbFlipV( pSourceShape->mbFlipV ) 173 , mbHidden( pSourceShape->mbHidden ) 174 , mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape ) 175 , mbLocked( pSourceShape->mbLocked ) 176 , mbLockedCanvas( pSourceShape->mbLockedCanvas ) 177 , mbWps( pSourceShape->mbWps ) 178 , mbTextBox( pSourceShape->mbTextBox ) 179 , maLinkedTxbxAttr() 180 , mbHasLinkedTxbx(false) 181 , maDiagramDoms( pSourceShape->maDiagramDoms ) 182 , mnZOrder(pSourceShape->mnZOrder) 183 , mnZOrderOff(pSourceShape->mnZOrderOff) 184 , mnDataNodeType(pSourceShape->mnDataNodeType) 185 , mfAspectRatio(pSourceShape->mfAspectRatio) 186 , mbUseBgFill(pSourceShape->mbUseBgFill) 187 {} 188 189 Shape::~Shape() 190 { 191 } 192 193 table::TablePropertiesPtr const & Shape::getTableProperties() 194 { 195 if ( !mpTablePropertiesPtr ) 196 mpTablePropertiesPtr = std::make_shared<table::TableProperties>(); 197 return mpTablePropertiesPtr; 198 } 199 200 void Shape::setDefaults(bool bHeight) 201 { 202 maDefaultShapeProperties.setProperty(PROP_TextAutoGrowHeight, false); 203 maDefaultShapeProperties.setProperty(PROP_TextWordWrap, true); 204 maDefaultShapeProperties.setProperty(PROP_TextLeftDistance, static_cast< sal_Int32 >( 250 )); 205 maDefaultShapeProperties.setProperty(PROP_TextUpperDistance, static_cast< sal_Int32 >( 125 )); 206 maDefaultShapeProperties.setProperty(PROP_TextRightDistance, static_cast< sal_Int32 >( 250 )); 207 maDefaultShapeProperties.setProperty(PROP_TextLowerDistance, static_cast< sal_Int32 >( 125 )); 208 if (bHeight) 209 maDefaultShapeProperties.setProperty(PROP_CharHeight, static_cast< float >( 18.0 )); 210 maDefaultShapeProperties.setProperty(PROP_TextVerticalAdjust, TextVerticalAdjust_TOP); 211 maDefaultShapeProperties.setProperty(PROP_ParaAdjust, static_cast< sal_Int16 >( ParagraphAdjust_CENTER )); 212 } 213 214 ::oox::vml::OleObjectInfo& Shape::setOleObjectType() 215 { 216 OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setOleObjectType - multiple frame types" ); 217 meFrameType = FRAMETYPE_OLEOBJECT; 218 mxOleObjectInfo = std::make_shared<::oox::vml::OleObjectInfo>( true ); 219 return *mxOleObjectInfo; 220 } 221 222 ChartShapeInfo& Shape::setChartType( bool bEmbedShapes ) 223 { 224 OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setChartType - multiple frame types" ); 225 meFrameType = FRAMETYPE_CHART; 226 if (mbWps) 227 msServiceName = "com.sun.star.drawing.temporaryForXMLImportOLE2Shape"; 228 else 229 msServiceName = "com.sun.star.drawing.OLE2Shape"; 230 mxChartShapeInfo = std::make_shared<ChartShapeInfo>( bEmbedShapes ); 231 return *mxChartShapeInfo; 232 } 233 234 void Shape::setDiagramType() 235 { 236 OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setDiagramType - multiple frame types" ); 237 meFrameType = FRAMETYPE_DIAGRAM; 238 msServiceName = "com.sun.star.drawing.GroupShape"; 239 mnSubType = 0; 240 } 241 242 void Shape::setTableType() 243 { 244 OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setTableType - multiple frame types" ); 245 meFrameType = FRAMETYPE_TABLE; 246 msServiceName = "com.sun.star.drawing.TableShape"; 247 mnSubType = 0; 248 } 249 250 void Shape::setServiceName( const char* pServiceName ) 251 { 252 if ( pServiceName ) 253 msServiceName = OUString::createFromAscii( pServiceName ); 254 } 255 256 const ShapeStyleRef* Shape::getShapeStyleRef( sal_Int32 nRefType ) const 257 { 258 ShapeStyleRefMap::const_iterator aIt = maShapeStyleRefs.find( nRefType ); 259 return (aIt == maShapeStyleRefs.end()) ? nullptr : &aIt->second; 260 } 261 262 void Shape::addShape( 263 ::oox::core::XmlFilterBase& rFilterBase, 264 const Theme* pTheme, 265 const Reference< XShapes >& rxShapes, 266 const basegfx::B2DHomMatrix& aTransformation, 267 FillProperties& rShapeOrParentShapeFillProps, 268 ShapeIdMap* pShapeMap, 269 bool bInGroup ) 270 { 271 SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId << "'"); 272 273 try 274 { 275 OUString sServiceName( msServiceName ); 276 if( !sServiceName.isEmpty() ) 277 { 278 basegfx::B2DHomMatrix aMatrix( aTransformation ); 279 Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, false, false, aMatrix, rShapeOrParentShapeFillProps, bInGroup ) ); 280 281 if( pShapeMap && !msId.isEmpty() ) 282 { 283 (*pShapeMap)[ msId ] = shared_from_this(); 284 } 285 286 // if this is a group shape, we have to add also each child shape 287 Reference< XShapes > xShapes( xShape, UNO_QUERY ); 288 if ( xShapes.is() ) 289 addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aMatrix ); 290 291 if( meFrameType == FRAMETYPE_DIAGRAM ) 292 { 293 keepDiagramCompatibilityInfo(); 294 if( !SvtFilterOptions::Get().IsSmartArt2Shape() ) 295 convertSmartArtToMetafile( rFilterBase ); 296 } 297 } 298 } 299 catch( const Exception& ) 300 { 301 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" ); 302 } 303 } 304 305 void Shape::setLockedCanvas(bool bLockedCanvas) 306 { 307 mbLockedCanvas = bLockedCanvas; 308 } 309 310 void Shape::setWps(bool bWps) 311 { 312 mbWps = bWps; 313 } 314 315 void Shape::setTextBox(bool bTextBox) 316 { 317 mbTextBox = bTextBox; 318 } 319 320 void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText ) 321 { 322 SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape.msId << "' to '" << msId << "'"); 323 324 if ( rReferencedShape.mpTextBody && bUseText ) 325 mpTextBody = std::make_shared<TextBody>( *rReferencedShape.mpTextBody ); 326 else 327 mpTextBody.reset(); 328 maShapeProperties = rReferencedShape.maShapeProperties; 329 mpShapeRefLinePropPtr = std::make_shared<LineProperties>( rReferencedShape.getActualLineProperties(nullptr) ); 330 mpShapeRefFillPropPtr = std::make_shared<FillProperties>( rReferencedShape.getActualFillProperties(nullptr, nullptr) ); 331 mpCustomShapePropertiesPtr = std::make_shared<CustomShapeProperties>( *rReferencedShape.mpCustomShapePropertiesPtr ); 332 mpTablePropertiesPtr = rReferencedShape.mpTablePropertiesPtr ? std::make_shared<table::TableProperties>( *rReferencedShape.mpTablePropertiesPtr ) : nullptr; 333 mpShapeRefEffectPropPtr = std::make_shared<EffectProperties>( rReferencedShape.getActualEffectProperties(nullptr) ); 334 mpMasterTextListStyle = std::make_shared<TextListStyle>( *rReferencedShape.mpMasterTextListStyle ); 335 maSize = rReferencedShape.maSize; 336 maPosition = rReferencedShape.maPosition; 337 mnRotation = rReferencedShape.mnRotation; 338 mbFlipH = rReferencedShape.mbFlipH; 339 mbFlipV = rReferencedShape.mbFlipV; 340 mbHidden = rReferencedShape.mbHidden; 341 mbLocked = rReferencedShape.mbLocked; 342 } 343 344 namespace { 345 346 struct ActionLockGuard 347 { 348 explicit ActionLockGuard(Reference<drawing::XShape> const& xShape) 349 : m_xLockable(xShape, UNO_QUERY) 350 { 351 if (m_xLockable.is()) { 352 m_xLockable->addActionLock(); 353 } 354 } 355 ~ActionLockGuard() 356 { 357 if (m_xLockable.is()) { 358 m_xLockable->removeActionLock(); 359 } 360 } 361 private: 362 Reference<document::XActionLockable> m_xLockable; 363 }; 364 365 } 366 367 // for group shapes, the following method is also adding each child 368 void Shape::addChildren( 369 XmlFilterBase& rFilterBase, 370 Shape& rMaster, 371 const Theme* pTheme, 372 const Reference< XShapes >& rxShapes, 373 ShapeIdMap* pShapeMap, 374 const basegfx::B2DHomMatrix& aTransformation ) 375 { 376 basegfx::B2DHomMatrix aChildTransformation; 377 378 aChildTransformation.translate(-maChPosition.X, -maChPosition.Y); 379 aChildTransformation.scale(1/(maChSize.Width ? maChSize.Width : 1.0), 1/(maChSize.Height ? maChSize.Height : 1.0)); 380 381 // Child position and size is typically non-zero, but it's allowed to have 382 // it like that, and in that case Word ignores the parent transformation 383 // (excluding translate component). 384 if (!mbWps || maChPosition.X || maChPosition.Y || maChSize.Width || maChSize.Height) 385 { 386 aChildTransformation *= aTransformation; 387 } 388 else 389 { 390 basegfx::B2DVector aScale, aTranslate; 391 double fRotate, fShearX; 392 aTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 393 aChildTransformation.translate(aTranslate.getX(), aTranslate.getY()); 394 } 395 396 SAL_INFO("oox.drawingml", "Shape::addChildren: parent matrix:\n" 397 << aChildTransformation.get(0, 0) << " " 398 << aChildTransformation.get(0, 1) << " " 399 << aChildTransformation.get(0, 2) << "\n" 400 << aChildTransformation.get(1, 0) << " " 401 << aChildTransformation.get(1, 1) << " " 402 << aChildTransformation.get(1, 2) << "\n" 403 << aChildTransformation.get(2, 0) << " " 404 << aChildTransformation.get(2, 1) << " " 405 << aChildTransformation.get(2, 2)); 406 407 for (auto const& child : rMaster.maChildren) 408 { 409 child->setMasterTextListStyle( mpMasterTextListStyle ); 410 child->addShape( rFilterBase, pTheme, rxShapes, aChildTransformation, getFillProperties(), pShapeMap, true ); 411 } 412 } 413 414 static void lcl_resetPropertyValue( std::vector<beans::PropertyValue>& rPropVec, const OUString& rName ) 415 { 416 auto aIterator = std::find_if( rPropVec.begin(), rPropVec.end(), 417 [rName]( const beans::PropertyValue& rValue ) { return rValue.Name == rName; } ); 418 419 if (aIterator != rPropVec.end()) 420 rPropVec.erase( aIterator ); 421 } 422 423 static void lcl_setPropertyValue( std::vector<beans::PropertyValue>& rPropVec, 424 const OUString& rName, 425 const beans::PropertyValue& rPropertyValue ) 426 { 427 lcl_resetPropertyValue( rPropVec, rName ); 428 429 rPropVec.push_back( rPropertyValue ); 430 } 431 432 static SdrTextHorzAdjust lcl_convertAdjust( ParagraphAdjust eAdjust ) 433 { 434 if (eAdjust == ParagraphAdjust_LEFT) 435 return SDRTEXTHORZADJUST_LEFT; 436 else if (eAdjust == ParagraphAdjust_RIGHT) 437 return SDRTEXTHORZADJUST_RIGHT; 438 else if (eAdjust == ParagraphAdjust_CENTER) 439 return SDRTEXTHORZADJUST_CENTER; 440 return SDRTEXTHORZADJUST_LEFT; 441 } 442 443 static void lcl_createPresetShape(const uno::Reference<drawing::XShape>& xShape, 444 const OUString& rClass, const OUString& rPresetType, 445 const CustomShapePropertiesPtr& pCustomShapePropertiesPtr, 446 const TextBodyPtr& pTextBody, 447 const GraphicHelper& rGraphicHelper) 448 { 449 if (!xShape.is() || !pCustomShapePropertiesPtr || !pTextBody) 450 return; 451 452 uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter( xShape, 453 uno::UNO_QUERY ); 454 455 if (!xDefaulter.is() || rClass.isEmpty()) 456 return; 457 458 Reference<XPropertySet> xSet( xShape, UNO_QUERY ); 459 if (!xSet.is()) 460 return; 461 462 // The DrawingML shapes from the presetTextWarpDefinitions are mapped to the definitions 463 // in svx/../EnhancedCustomShapeGeometry.cxx, which are used for WordArt shapes from 464 // binary MS Office. Therefore all adjustment values need to be adapted. 465 auto aAdjGdList = pCustomShapePropertiesPtr->getAdjustmentGuideList(); 466 Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustment( 467 !aAdjGdList.empty() ? aAdjGdList.size() : 1 ); 468 469 int nIndex = 0; 470 for (const auto& aEntry : aAdjGdList) 471 { 472 double fValue = aEntry.maFormula.toDouble(); 473 // then: polar-handle, else: XY-handle 474 // There exist only 8 polar-handles at all in presetTextWarp. 475 if ((rClass == "fontwork-arch-down-curve") 476 || (rClass == "fontwork-arch-down-pour" && aEntry.maName == "adj1") 477 || (rClass == "fontwork-arch-up-curve") 478 || (rClass == "fontwork-arch-up-pour" && aEntry.maName == "adj1") 479 || (rClass == "fontwork-open-circle-curve") 480 || (rClass == "fontwork-open-circle-pour" && aEntry.maName == "adj1") 481 || (rClass == "fontwork-circle-curve") 482 || (rClass == "fontwork-circle-pour" && aEntry.maName == "adj1")) 483 { 484 // DrawingML has 1/60000 degree unit, but WordArt simple degree. Range [0..360[ 485 // or range ]-180..180] doesn't matter, because only cos(angle) and 486 // sin(angle) are used. 487 fValue = NormAngle360(fValue / 60000.0); 488 } 489 else 490 { 491 // DrawingML writes adjustment guides as relative value with 100% = 100000, 492 // but WordArt definitions use values absolute in viewBox 0 0 21600 21600, 493 // so scale with 21600/100000 = 0.216, with two exceptions: 494 // X-handles of waves describe increase/decrease relative to horizontal center. 495 // The gdRefR of pour-shapes is not relative to viewBox but to radius. 496 if ((rClass == "mso-spt158" && aEntry.maName == "adj2") // textDoubleWave1 497 || (rClass == "fontwork-wave" && aEntry.maName == "adj2") // textWave1 498 || (rClass == "mso-spt157" && aEntry.maName == "adj2") // textWave2 499 || (rClass == "mso-spt159" && aEntry.maName == "adj2")) // textWave4 500 { 501 fValue = (fValue + 50000.0) * 0.216; 502 } 503 else if ( (rClass == "fontwork-arch-down-pour" && aEntry.maName == "adj2") 504 || (rClass == "fontwork-arch-up-pour" && aEntry.maName == "adj2") 505 || (rClass == "fontwork-open-circle-pour" && aEntry.maName == "adj2") 506 || (rClass == "fontwork-circle-pour" && aEntry.maName == "adj2")) 507 { 508 fValue *= 0.108; 509 } 510 else 511 { 512 fValue *= 0.216; 513 } 514 } 515 516 aAdjustment[nIndex].Value <<= fValue; 517 aAdjustment[nIndex++].State = css::beans::PropertyState_DIRECT_VALUE; 518 } 519 520 // Set properties 521 xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::makeAny( false ) ); 522 xSet->setPropertyValue( UNO_NAME_TEXT_AUTOGROWWIDTH, uno::makeAny( false ) ); 523 xSet->setPropertyValue( UNO_NAME_FILLSTYLE, uno::makeAny( drawing::FillStyle_SOLID ) ); 524 525 // ToDo: Old binary WordArt does not allow different styles for different paragraphs, so it 526 // was not necessary to examine all paragraphs. Solution for DrawingML is needed. 527 // Currently different alignment of paragraphs are lost, for example. 528 const TextParagraphVector& rParagraphs = pTextBody->getParagraphs(); 529 if (!rParagraphs.empty() && !rParagraphs[0]->getRuns().empty()) 530 { 531 std::shared_ptr<TextParagraph> pParagraph = rParagraphs[0]; 532 std::shared_ptr<TextRun> pRun = pParagraph->getRuns()[0]; 533 TextCharacterProperties& pProperties = pRun->getTextCharacterProperties(); 534 535 if (pProperties.moBold.has() && pProperties.moBold.get()) 536 { 537 xSet->setPropertyValue( UNO_NAME_CHAR_WEIGHT, uno::makeAny( css::awt::FontWeight::BOLD ) ); 538 } 539 if (pProperties.moItalic.has() && pProperties.moItalic.get()) 540 { 541 xSet->setPropertyValue( UNO_NAME_CHAR_POSTURE, uno::makeAny( css::awt::FontSlant::FontSlant_ITALIC ) ); 542 } 543 if (pProperties.moHeight.has()) 544 { 545 sal_Int32 nHeight = pProperties.moHeight.get() / 100; 546 xSet->setPropertyValue( UNO_NAME_CHAR_HEIGHT, uno::makeAny( nHeight ) ); 547 } 548 if (pProperties.maFillProperties.maFillColor.isUsed()) 549 { 550 const sal_Int32 aFillColor = static_cast<sal_Int32>( 551 pProperties.maFillProperties.maFillColor.getColor( rGraphicHelper ).GetRGBColor() ); 552 xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( aFillColor ) ); 553 } 554 else 555 { 556 // Set default color 557 xSet->setPropertyValue( UNO_NAME_FILLCOLOR, uno::makeAny( COL_BLACK ) ); 558 } 559 { 560 ParagraphAdjust eAdjust = ParagraphAdjust_LEFT; 561 if (pParagraph->getProperties().getParaAdjust()) 562 eAdjust = *pParagraph->getProperties().getParaAdjust(); 563 xSet->setPropertyValue( "ParaAdjust", uno::makeAny( eAdjust ) ); 564 SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>( xShape ); 565 assert(pShape); 566 SdrTextHorzAdjust eHorzAdjust = lcl_convertAdjust( eAdjust ); 567 pShape->GetSdrObject()->SetMergedItem( SdrTextHorzAdjustItem( eHorzAdjust ) ); 568 } 569 } 570 571 // Apply vertical adjustment for text on arc 572 // ToDo: The property is currently not evaluated. 573 SvxShape* pShape = comphelper::getUnoTunnelImplementation<SvxShape>(xShape); 574 assert(pShape); 575 if (rClass == "fontwork-arch-up-curve") 576 pShape->GetSdrObject()->SetMergedItem( SdrTextVertAdjustItem( SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM ) ); 577 else if (rClass == "fontwork-arch-down-curve") 578 pShape->GetSdrObject()->SetMergedItem( SdrTextVertAdjustItem( SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP ) ); 579 580 // Apply preset shape 581 xDefaulter->createCustomShapeDefaults( rClass ); 582 583 auto aGeomPropSeq = xSet->getPropertyValue( "CustomShapeGeometry" ) 584 .get<uno::Sequence<beans::PropertyValue>>(); 585 auto aGeomPropVec 586 = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>( 587 aGeomPropSeq ); 588 589 // Reset old properties 590 const OUString sTextPath( "TextPath" ); 591 const OUString sAdjustmentValues( "AdjustmentValues" ); 592 const OUString sPresetTextWarp( "PresetTextWarp" ); 593 594 lcl_resetPropertyValue( aGeomPropVec, "CoordinateSize" ); 595 lcl_resetPropertyValue( aGeomPropVec, "Equations" ); 596 lcl_resetPropertyValue( aGeomPropVec, "Path" ); 597 lcl_resetPropertyValue( aGeomPropVec, sAdjustmentValues); 598 599 bool bFromWordArt(false); 600 pTextBody->getTextProperties().maPropertyMap.getProperty(PROP_FromWordArt) >>= bFromWordArt; 601 602 bool bScaleX(false); 603 if (!bFromWordArt 604 && (rPresetType == "textArchDown" || rPresetType == "textArchUp" 605 || rPresetType == "textCircle" || rPresetType == "textButton")) 606 { 607 bScaleX = true; 608 } 609 610 // Apply geometry properties 611 uno::Sequence<beans::PropertyValue> aPropertyValues( 612 comphelper::InitPropertySequence( 613 { { sTextPath, uno::makeAny( true ) }, 614 { "TextPathMode", 615 uno::Any( drawing::EnhancedCustomShapeTextPathMode_PATH ) }, 616 { "ScaleX", uno::Any(bScaleX) } } ) ); 617 618 lcl_setPropertyValue( aGeomPropVec, sTextPath, 619 comphelper::makePropertyValue( sTextPath, aPropertyValues ) ); 620 621 lcl_setPropertyValue( aGeomPropVec, sPresetTextWarp, 622 comphelper::makePropertyValue( sPresetTextWarp, rPresetType ) ); 623 624 if (!aAdjGdList.empty()) 625 { 626 lcl_setPropertyValue( aGeomPropVec, sAdjustmentValues, 627 comphelper::makePropertyValue( sAdjustmentValues, aAdjustment ) ); 628 } 629 630 xSet->setPropertyValue( 631 "CustomShapeGeometry", 632 uno::makeAny(comphelper::containerToSequence(aGeomPropVec))); 633 } 634 635 Reference< XShape > const & Shape::createAndInsert( 636 ::oox::core::XmlFilterBase& rFilterBase, 637 const OUString& rServiceName, 638 const Theme* pTheme, 639 const css::uno::Reference< css::drawing::XShapes >& rxShapes, 640 bool bClearText, 641 bool bDoNotInsertEmptyTextBody, 642 basegfx::B2DHomMatrix& aParentTransformation, 643 FillProperties& rShapeOrParentShapeFillProps, 644 bool bInGroup ) 645 { 646 bool bIsEmbMedia = false; 647 SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId << "' service='" << rServiceName << "'"); 648 649 formulaimport::XmlStreamBuilder * pMathXml(nullptr); 650 if (mpTextBody) 651 { 652 for (auto const& it : mpTextBody->getParagraphs()) 653 { 654 if (it->HasMathXml()) 655 { 656 if (!mpTextBody->isEmpty() || pMathXml != nullptr) 657 { 658 SAL_WARN("oox.drawingml", "losing a Math object..."); 659 } 660 else 661 { 662 pMathXml = &it->GetMathXml(); 663 } 664 } 665 } 666 } 667 668 // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height 669 if ( mpTablePropertiesPtr && rServiceName == "com.sun.star.drawing.TableShape" ) 670 { 671 maSize.Width = 0; 672 for (auto const& elem : mpTablePropertiesPtr->getTableGrid()) 673 { 674 maSize.Width = o3tl::saturating_add(maSize.Width, static_cast<sal_Int32>(elem)); 675 } 676 maSize.Height = 0; 677 for (auto const& elem : mpTablePropertiesPtr->getTableRows()) 678 { 679 maSize.Height = o3tl::saturating_add(maSize.Height, elem.getHeight()); 680 } 681 } 682 683 awt::Rectangle aShapeRectHmm( maPosition.X / EMU_PER_HMM, maPosition.Y / EMU_PER_HMM, maSize.Width / EMU_PER_HMM, maSize.Height / EMU_PER_HMM ); 684 685 OUString aServiceName; 686 if (pMathXml) 687 { 688 // convert this shape to OLE 689 aServiceName = "com.sun.star.drawing.OLE2Shape"; 690 msServiceName = aServiceName; 691 meFrameType = FRAMETYPE_GENERIC; // not OLEOBJECT, no stream in package 692 mnSubType = 0; 693 } 694 else if (rServiceName == "com.sun.star.drawing.GraphicObjectShape" && 695 mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty()) 696 { 697 aServiceName = finalizeServiceName( rFilterBase, "com.sun.star.presentation.MediaShape", aShapeRectHmm ); 698 bIsEmbMedia = true; 699 } 700 else 701 { 702 aServiceName = finalizeServiceName( rFilterBase, rServiceName, aShapeRectHmm ); 703 } 704 // Use custom shape instead of GraphicObjectShape if the image is cropped to 705 // shape. Except rectangle, which does not require further cropping 706 bool bIsCroppedGraphic = (aServiceName == "com.sun.star.drawing.GraphicObjectShape" && mpCustomShapePropertiesPtr->getShapePresetType() >= 0 707 && mpCustomShapePropertiesPtr->getShapePresetType() != XML_Rect && mpCustomShapePropertiesPtr->getShapePresetType() != XML_rect); 708 bool bIsCustomShape = ( aServiceName == "com.sun.star.drawing.CustomShape" || 709 aServiceName == "com.sun.star.drawing.ConnectorShape" || 710 bIsCroppedGraphic); 711 if(bIsCroppedGraphic) 712 { 713 aServiceName = "com.sun.star.drawing.CustomShape"; 714 mpGraphicPropertiesPtr->mbIsCustomShape = true; 715 } 716 bool bUseRotationTransform = ( !mbWps || 717 aServiceName == "com.sun.star.drawing.LineShape" || 718 aServiceName == "com.sun.star.drawing.GroupShape" || 719 mbFlipH || 720 mbFlipV ); 721 722 basegfx::B2DHomMatrix aTransformation; 723 724 if (bUseRotationTransform && mnDiagramRotation != 0) 725 { 726 // rotate diagram's shape around object's center before sizing 727 aTransformation.translate(-0.5, -0.5); 728 aTransformation.rotate(basegfx::deg2rad(mnDiagramRotation / 60000.0)); 729 aTransformation.translate(0.5, 0.5); 730 } 731 732 if( maSize.Width != 1 || maSize.Height != 1) 733 { 734 // take care there are no zeros used by error 735 aTransformation.scale( 736 maSize.Width ? maSize.Width : 1.0, 737 maSize.Height ? maSize.Height : 1.0 ); 738 } 739 740 bool bNoTranslation = !aParentTransformation.isIdentity(); 741 if( mbFlipH || mbFlipV || mnRotation != 0 || bNoTranslation ) 742 { 743 // calculate object's center 744 basegfx::B2DPoint aCenter(0.5, 0.5); 745 aCenter *= aTransformation; 746 747 // center object at origin 748 aTransformation.translate( -aCenter.getX(), -aCenter.getY() ); 749 750 if( !bIsCustomShape && ( mbFlipH || mbFlipV ) ) 751 { 752 // mirror around object's center 753 aTransformation.scale( mbFlipH ? -1.0 : 1.0, mbFlipV ? -1.0 : 1.0 ); 754 } 755 756 if( bUseRotationTransform ) 757 { 758 // OOXML flips shapes before rotating them. 759 if( bIsCustomShape ) 760 { 761 basegfx::B2DVector aScale, aTranslate; 762 double fRotate, fShearX; 763 aParentTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 764 // A negative scale means that the shape needs to be flipped 765 if(aScale.getX() < 0) 766 { 767 mbFlipH = !mbFlipH; 768 aTransformation.scale(-1, 1); 769 } 770 if(aScale.getY() < 0) 771 { 772 mbFlipV = !mbFlipV; 773 aTransformation.scale(1, -1); 774 } 775 } 776 // rotate around object's center 777 aTransformation.rotate(basegfx::deg2rad(static_cast<double>(mnRotation) / 60000.0)); 778 } 779 780 // move object back from center 781 aTransformation.translate( aCenter.getX(), aCenter.getY() ); 782 } 783 784 if( maPosition.X != 0 || maPosition.Y != 0) 785 { 786 // if global position is used, add it to transformation 787 if (mbWps && !bInGroup) 788 aTransformation.translate( maPosition.X * EMU_PER_HMM, maPosition.Y * EMU_PER_HMM); 789 else 790 aTransformation.translate( maPosition.X, maPosition.Y ); 791 } 792 793 aTransformation = aParentTransformation*aTransformation; 794 aParentTransformation = aTransformation; 795 aTransformation.scale(1/double(EMU_PER_HMM), 1/double(EMU_PER_HMM)); 796 797 if( bIsCustomShape && mbFlipH != mbFlipV ) 798 { 799 basegfx::B2DVector aScale, aTranslate; 800 double fRotate, fShearX; 801 aTransformation.decompose(aScale, aTranslate, fRotate, fShearX); 802 803 if(fRotate != 0) 804 { 805 // calculate object's center 806 basegfx::B2DPoint aCenter(0.5, 0.5); 807 aCenter *= aTransformation; 808 aTransformation.translate( -aCenter.getX(), -aCenter.getY() ); 809 // OOXML flips shapes before rotating them, so the rotation needs to be inverted 810 aTransformation.rotate( fRotate * -2.0 ); 811 aTransformation.translate( aCenter.getX(), aCenter.getY() ); 812 } 813 } 814 815 // special for lineshape 816 if ( aServiceName == "com.sun.star.drawing.LineShape" ) 817 { 818 ::basegfx::B2DPolygon aPoly; 819 aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); 820 aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); 821 aPoly.transform( aTransformation ); 822 823 // now creating the corresponding PolyPolygon 824 sal_Int32 i, nNumPoints = aPoly.count(); 825 uno::Sequence< awt::Point > aPointSequence( nNumPoints ); 826 awt::Point* pPoints = aPointSequence.getArray(); 827 uno::Reference<lang::XServiceInfo> xModelInfo(rFilterBase.getModel(), uno::UNO_QUERY); 828 bool bIsWriter = xModelInfo->supportsService("com.sun.star.text.TextDocument"); 829 for( i = 0; i < nNumPoints; ++i ) 830 { 831 const basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) ); 832 833 // tdf#106792 Not needed anymore due to the change in SdrPathObj::NbcResize: 834 // tdf#96674: Guard against zero width or height. 835 836 if (bIsWriter && bNoTranslation) 837 // Writer's draw page is in twips, and these points get passed 838 // to core without any unit conversion when Writer 839 // postprocesses only the group shape itself. 840 pPoints[i] = awt::Point(static_cast<sal_Int32>(convertMm100ToTwip(aPoint.getX())), static_cast<sal_Int32>(convertMm100ToTwip(aPoint.getY()))); 841 else 842 pPoints[i] = awt::Point(static_cast<sal_Int32>(aPoint.getX()), static_cast<sal_Int32>(aPoint.getY())); 843 } 844 uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 ); 845 aPolyPolySequence.getArray()[ 0 ] = aPointSequence; 846 847 maShapeProperties.setProperty(PROP_PolyPolygon, aPolyPolySequence); 848 } 849 else if ( aServiceName == "com.sun.star.drawing.ConnectorShape" ) 850 { 851 ::basegfx::B2DPolygon aPoly; 852 aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) ); 853 aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) ); 854 aPoly.transform( aTransformation ); 855 856 basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) ); 857 basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) ); 858 awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) ); 859 awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) ); 860 861 maShapeProperties.setProperty(PROP_StartPosition, aAWTStartPosition); 862 maShapeProperties.setProperty(PROP_EndPosition, aAWTEndPosition); 863 } 864 else 865 { 866 // now set transformation for this object 867 HomogenMatrix3 aMatrix; 868 869 aMatrix.Line1.Column1 = aTransformation.get(0,0); 870 aMatrix.Line1.Column2 = aTransformation.get(0,1); 871 aMatrix.Line1.Column3 = aTransformation.get(0,2); 872 873 aMatrix.Line2.Column1 = aTransformation.get(1,0); 874 aMatrix.Line2.Column2 = aTransformation.get(1,1); 875 aMatrix.Line2.Column3 = aTransformation.get(1,2); 876 877 aMatrix.Line3.Column1 = aTransformation.get(2,0); 878 aMatrix.Line3.Column2 = aTransformation.get(2,1); 879 aMatrix.Line3.Column3 = aTransformation.get(2,2); 880 881 maShapeProperties.setProperty(PROP_Transformation, aMatrix); 882 } 883 884 Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); 885 if ( !mxShape.is() ) 886 mxShape.set( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW ); 887 888 Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); 889 if (xSet.is()) 890 { 891 if( !msName.isEmpty() ) 892 { 893 Reference< container::XNamed > xNamed( mxShape, UNO_QUERY ); 894 if( xNamed.is() ) 895 xNamed->setName( msName ); 896 } 897 if( !msDescription.isEmpty() ) 898 { 899 xSet->setPropertyValue( "Description", Any( msDescription ) ); 900 } 901 if (aServiceName != "com.sun.star.text.TextFrame") 902 rxShapes->add( mxShape ); 903 904 if ( mbHidden || mbHiddenMasterShape ) 905 { 906 SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId << "'"); 907 xSet->setPropertyValue( "Visible", Any( false ) ); 908 // In Excel hidden means not printed, let's use visibility for now until that's handled separately 909 xSet->setPropertyValue( "Printable", Any( false ) ); 910 } 911 912 if (mbLocked) 913 { 914 xSet->setPropertyValue("MoveProtect", Any(true)); 915 xSet->setPropertyValue("SizeProtect", Any(true)); 916 } 917 918 ActionLockGuard const alg(mxShape); 919 920 // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape 921 if ( bClearText ) 922 { 923 uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY ); 924 if ( xText.is() ) 925 { 926 xText->setString( "" ); 927 } 928 } 929 930 if (pMathXml) 931 { 932 // the "EmbeddedObject" property is read-only, so we have to create 933 // the shape first, and it can be read only after the shape is 934 // inserted into the document, so delay the actual import until here 935 SvGlobalName name(SO3_SM_CLASSID); 936 xSet->setPropertyValue("CLSID", uno::makeAny(name.GetHexName())); 937 uno::Reference<embed::XEmbeddedObject> const xObj( 938 xSet->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY); 939 if (xObj.is()) 940 { 941 uno::Reference<uno::XInterface> const xMathModel(xObj->getComponent()); 942 oox::FormulaImportBase *const pMagic( 943 dynamic_cast<oox::FormulaImportBase*>(xMathModel.get())); 944 assert(pMagic); 945 pMagic->readFormulaOoxml(*pMathXml); 946 } 947 } 948 949 const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper(); 950 951 ::Color nLinePhClr(0xffffffff); 952 ::Color nFillPhClr(0xffffffff); 953 // TODO: use ph color when applying effect properties 954 //sal_Int32 nEffectPhClr = -1; 955 956 if( pTheme ) 957 { 958 if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) ) 959 { 960 LineProperties aLineProperties; 961 aLineProperties.maLineFill.moFillType = XML_noFill; 962 if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) ) 963 aLineProperties.assignUsed( *pLineProps ); 964 nLinePhClr = pLineRef->maPhClr.getColor( rGraphicHelper ); 965 966 // Store style-related properties to InteropGrabBag to be able to export them back 967 uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( 968 { 969 {"SchemeClr", uno::makeAny(pLineRef->maPhClr.getSchemeName())}, 970 {"Idx", uno::makeAny(pLineRef->mnThemedIdx)}, 971 {"Color", uno::makeAny(nLinePhClr)}, 972 {"LineStyle", uno::makeAny(aLineProperties.getLineStyle())}, 973 {"LineCap", uno::makeAny(aLineProperties.getLineCap())}, 974 {"LineJoint", uno::makeAny(aLineProperties.getLineJoint())}, 975 {"LineWidth", uno::makeAny(aLineProperties.getLineWidth())}, 976 {"Transformations", uno::makeAny(pLineRef->maPhClr.getTransformations())} 977 }); 978 putPropertyToGrabBag( "StyleLnRef", Any( aProperties ) ); 979 } 980 if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) ) 981 { 982 if (!mbUseBgFill) 983 { 984 nFillPhClr = pFillRef->maPhClr.getColor(rGraphicHelper); 985 } 986 987 OUString sColorScheme = pFillRef->maPhClr.getSchemeName(); 988 if( !sColorScheme.isEmpty() ) 989 { 990 uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( 991 { 992 {"SchemeClr", uno::makeAny(sColorScheme)}, 993 {"Idx", uno::makeAny(pFillRef->mnThemedIdx)}, 994 {"Color", uno::makeAny(nFillPhClr)}, 995 {"Transformations", uno::makeAny(pFillRef->maPhClr.getTransformations())} 996 }); 997 998 putPropertyToGrabBag( "StyleFillRef", Any( aProperties ) ); 999 } 1000 } 1001 if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) ) 1002 { 1003 // TODO: use ph color when applying effect properties 1004 // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper ); 1005 1006 // Store style-related properties to InteropGrabBag to be able to export them back 1007 uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence( 1008 { 1009 {"SchemeClr", uno::makeAny(pEffectRef->maPhClr.getSchemeName())}, 1010 {"Idx", uno::makeAny(pEffectRef->mnThemedIdx)}, 1011 {"Transformations", uno::makeAny(pEffectRef->maPhClr.getTransformations())} 1012 }); 1013 putPropertyToGrabBag( "StyleEffectRef", Any( aProperties ) ); 1014 } 1015 } 1016 ShapePropertyMap aShapeProps( rFilterBase.getModelObjectHelper() ); 1017 1018 // add properties from textbody to shape properties 1019 if( mpTextBody ) 1020 { 1021 mpTextBody->getTextProperties().pushRotationAdjustments(); 1022 aShapeProps.assignUsed( mpTextBody->getTextProperties().maPropertyMap ); 1023 // Push char properties as well - specifically useful when this is a placeholder 1024 if( mpMasterTextListStyle && mpMasterTextListStyle->getListStyle()[0]->getTextCharacterProperties().moHeight.has() ) 1025 aShapeProps.setProperty(PROP_CharHeight, GetFontHeight( mpMasterTextListStyle->getListStyle()[0]->getTextCharacterProperties().moHeight.get() )); 1026 } 1027 1028 // applying properties 1029 aShapeProps.assignUsed( getShapeProperties() ); 1030 aShapeProps.assignUsed( maDefaultShapeProperties ); 1031 if ( bIsEmbMedia || aServiceName == "com.sun.star.drawing.GraphicObjectShape" || aServiceName == "com.sun.star.drawing.OLE2Shape" || bIsCustomShape ) 1032 mpGraphicPropertiesPtr->pushToPropMap( aShapeProps, rGraphicHelper ); 1033 if ( mpTablePropertiesPtr && aServiceName == "com.sun.star.drawing.TableShape" ) 1034 mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle ); 1035 1036 FillProperties aFillProperties = getActualFillProperties(pTheme, &rShapeOrParentShapeFillProps); 1037 if (getFillProperties().moFillType.has() && getFillProperties().moFillType.get() == XML_grpFill) 1038 getFillProperties().assignUsed(aFillProperties); 1039 if(!bIsCroppedGraphic) 1040 aFillProperties.pushToPropMap( aShapeProps, rGraphicHelper, mnRotation, nFillPhClr, mbFlipH, mbFlipV ); 1041 LineProperties aLineProperties = getActualLineProperties(pTheme); 1042 aLineProperties.pushToPropMap( aShapeProps, rGraphicHelper, nLinePhClr ); 1043 EffectProperties aEffectProperties = getActualEffectProperties(pTheme); 1044 // TODO: use ph color when applying effect properties 1045 aEffectProperties.pushToPropMap( aShapeProps, rGraphicHelper ); 1046 1047 // applying autogrowheight property before setting shape size, because 1048 // the shape size might be changed if currently autogrowheight is true 1049 // we must also check that the PropertySet supports the property. 1050 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); 1051 const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight ); 1052 if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) ) 1053 if( aShapeProps.hasProperty( PROP_TextAutoGrowHeight ) ) 1054 xSet->setPropertyValue( rPropName, Any( false ) ); 1055 1056 // do not set properties at a group shape (this causes 1057 // assertions from svx) ... 1058 if( aServiceName != "com.sun.star.drawing.GroupShape" ) 1059 { 1060 if (aServiceName == "com.sun.star.text.TextFrame") 1061 { 1062 if (mpCustomShapePropertiesPtr && mpCustomShapePropertiesPtr->getShapeTypeOverride()) 1063 { 1064 uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); 1065 uno::Sequence<beans::PropertyValue> aGrabBag; 1066 propertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag; 1067 sal_Int32 length = aGrabBag.getLength(); 1068 aGrabBag.realloc( length+1); 1069 aGrabBag[length].Name = "mso-orig-shape-type"; 1070 uno::Sequence< sal_Int8 > const & aNameSeq = 1071 mpCustomShapePropertiesPtr->getShapePresetTypeName(); 1072 OUString sShapePresetTypeName(reinterpret_cast< const char* >( 1073 aNameSeq.getConstArray()), aNameSeq.getLength(), RTL_TEXTENCODING_UTF8); 1074 aGrabBag[length].Value <<= sShapePresetTypeName; 1075 propertySet->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aGrabBag)); 1076 } 1077 //If the text box has links then save the link information so that 1078 //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames. 1079 if (isLinkedTxbx()) 1080 { 1081 uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); 1082 uno::Sequence<beans::PropertyValue> aGrabBag; 1083 propertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag; 1084 sal_Int32 length = aGrabBag.getLength(); 1085 aGrabBag.realloc( length + 3 ); 1086 aGrabBag[length].Name = "TxbxHasLink"; 1087 aGrabBag[length].Value <<= isLinkedTxbx(); 1088 aGrabBag[length + 1 ].Name = "Txbx-Id"; 1089 aGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id; 1090 aGrabBag[length + 2 ].Name = "Txbx-Seq"; 1091 aGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq; 1092 propertySet->setPropertyValue("FrameInteropGrabBag",uno::makeAny(aGrabBag)); 1093 } 1094 1095 // TextFrames have BackColor, not FillColor 1096 if (aShapeProps.hasProperty(PROP_FillColor)) 1097 { 1098 aShapeProps.setAnyProperty(PROP_BackColor, aShapeProps.getProperty(PROP_FillColor)); 1099 aShapeProps.erase(PROP_FillColor); 1100 } 1101 // TextFrames have BackColorTransparency, not FillTransparence 1102 if (aShapeProps.hasProperty(PROP_FillTransparence)) 1103 { 1104 aShapeProps.setAnyProperty(PROP_BackColorTransparency, aShapeProps.getProperty(PROP_FillTransparence)); 1105 aShapeProps.erase(PROP_FillTransparence); 1106 } 1107 // TextFrames have BackGraphic, not FillBitmap 1108 if (aShapeProps.hasProperty(PROP_FillBitmap)) 1109 { 1110 aShapeProps.setAnyProperty(PROP_BackGraphic, aShapeProps.getProperty(PROP_FillBitmap)); 1111 aShapeProps.erase(PROP_FillBitmap); 1112 } 1113 if (aShapeProps.hasProperty(PROP_FillBitmapName)) 1114 { 1115 uno::Any aAny = aShapeProps.getProperty(PROP_FillBitmapName); 1116 OUString aFillBitmapName = aAny.get<OUString>(); 1117 uno::Reference<awt::XBitmap> xBitmap = rFilterBase.getModelObjectHelper().getFillBitmap(aFillBitmapName); 1118 uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY); 1119 aShapeProps.setProperty(PROP_BackGraphic, xGraphic); 1120 // aShapeProps.erase(PROP_FillBitmapName); // Maybe, leave the name as well 1121 } 1122 // And no LineColor property; individual borders can have colors 1123 if (aShapeProps.hasProperty(PROP_LineColor)) 1124 { 1125 uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); 1126 static const sal_Int32 aBorders[] = 1127 { 1128 PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder 1129 }; 1130 for (sal_Int32 nBorder : aBorders) 1131 { 1132 css::table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(nBorder)).get<css::table::BorderLine2>(); 1133 aBorderLine.Color = aShapeProps.getProperty(PROP_LineColor).get<sal_Int32>(); 1134 if (aLineProperties.moLineWidth.has()) 1135 aBorderLine.LineWidth = convertEmuToHmm(aLineProperties.moLineWidth.get()); 1136 aShapeProps.setProperty(nBorder, aBorderLine); 1137 } 1138 aShapeProps.erase(PROP_LineColor); 1139 } 1140 if(mnRotation) 1141 { 1142 uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); 1143 const OUString aGrabBagPropName = "FrameInteropGrabBag"; 1144 uno::Sequence<beans::PropertyValue> aGrabBag; 1145 xPropertySet->getPropertyValue(aGrabBagPropName) >>= aGrabBag; 1146 beans::PropertyValue aPair; 1147 aPair.Name = "mso-rotation-angle"; 1148 aPair.Value <<= mnRotation; 1149 if (aGrabBag.hasElements()) 1150 { 1151 sal_Int32 nLength = aGrabBag.getLength(); 1152 aGrabBag.realloc(nLength + 1); 1153 aGrabBag[nLength] = aPair; 1154 } 1155 else 1156 { 1157 aGrabBag.realloc(1); 1158 aGrabBag[0] = aPair; 1159 } 1160 xPropertySet->setPropertyValue(aGrabBagPropName, uno::makeAny(aGrabBag)); 1161 } 1162 // TextFrames have ShadowFormat, not individual shadow properties. 1163 std::optional<sal_Int32> oShadowDistance; 1164 if (aShapeProps.hasProperty(PROP_ShadowXDistance)) 1165 { 1166 oShadowDistance = aShapeProps.getProperty(PROP_ShadowXDistance).get<sal_Int32>(); 1167 aShapeProps.erase(PROP_ShadowXDistance); 1168 } 1169 if (aShapeProps.hasProperty(PROP_ShadowYDistance)) 1170 { 1171 // There is a single 'dist' attribute, so no need to count the avg of x and y. 1172 aShapeProps.erase(PROP_ShadowYDistance); 1173 } 1174 std::optional<sal_Int32> oShadowColor; 1175 if (aShapeProps.hasProperty(PROP_ShadowColor)) 1176 { 1177 oShadowColor = aShapeProps.getProperty(PROP_ShadowColor).get<sal_Int32>(); 1178 aShapeProps.erase(PROP_ShadowColor); 1179 } 1180 if (aShapeProps.hasProperty(PROP_Shadow)) 1181 aShapeProps.erase(PROP_Shadow); 1182 1183 if (oShadowDistance || oShadowColor || aEffectProperties.maShadow.moShadowDir.has()) 1184 { 1185 css::table::ShadowFormat aFormat; 1186 if (oShadowColor) 1187 aFormat.Color = *oShadowColor; 1188 if (aEffectProperties.maShadow.moShadowDir.has()) 1189 { 1190 css::table::ShadowLocation nLocation = css::table::ShadowLocation_NONE; 1191 switch (aEffectProperties.maShadow.moShadowDir.get()) 1192 { 1193 case 13500000: 1194 nLocation = css::table::ShadowLocation_TOP_LEFT; 1195 break; 1196 case 18900000: 1197 nLocation = css::table::ShadowLocation_TOP_RIGHT; 1198 break; 1199 case 8100000: 1200 nLocation = css::table::ShadowLocation_BOTTOM_LEFT; 1201 break; 1202 case 2700000: 1203 nLocation = css::table::ShadowLocation_BOTTOM_RIGHT; 1204 break; 1205 } 1206 aFormat.Location = nLocation; 1207 } 1208 aFormat.ShadowWidth = *oShadowDistance; 1209 aShapeProps.setProperty(PROP_ShadowFormat, aFormat); 1210 } 1211 1212 } 1213 else if (mbTextBox) 1214 { 1215 aShapeProps.setProperty(PROP_TextBox, true); 1216 } 1217 1218 if (aServiceName != "com.sun.star.text.TextFrame" && isLinkedTxbx()) 1219 { 1220 uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); 1221 uno::Sequence<beans::PropertyValue> aGrabBag; 1222 propertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag; 1223 sal_Int32 length = aGrabBag.getLength(); 1224 aGrabBag.realloc( length + 3 ); 1225 aGrabBag[length].Name = "TxbxHasLink"; 1226 aGrabBag[length].Value <<= isLinkedTxbx(); 1227 aGrabBag[length + 1 ].Name = "Txbx-Id"; 1228 aGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id; 1229 aGrabBag[length + 2 ].Name = "Txbx-Seq"; 1230 aGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq; 1231 propertySet->setPropertyValue("InteropGrabBag",uno::makeAny(aGrabBag)); 1232 } 1233 1234 PropertySet( xSet ).setProperties( aShapeProps ); 1235 if (mbLockedCanvas) 1236 { 1237 putPropertyToGrabBag( "LockedCanvas", Any( true ) ); 1238 if (aServiceName == "com.sun.star.drawing.LineShape") 1239 { 1240 // It seems the position and size for lines inside a locked canvas is absolute. 1241 mxShape->setPosition(awt::Point(aShapeRectHmm.X, aShapeRectHmm.Y)); 1242 mxShape->setSize(awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height)); 1243 } 1244 } 1245 1246 // Store original fill and line colors of the shape and the theme color name to InteropGrabBag 1247 std::vector<beans::PropertyValue> aProperties; 1248 aProperties.push_back(comphelper::makePropertyValue("EmuLineWidth", aLineProperties.moLineWidth.get(0))); 1249 aProperties.push_back(comphelper::makePropertyValue("OriginalSolidFillClr", aShapeProps.getProperty(PROP_FillColor))); 1250 aProperties.push_back(comphelper::makePropertyValue("OriginalLnSolidFillClr", aShapeProps.getProperty(PROP_LineColor))); 1251 OUString sColorFillScheme = aFillProperties.maFillColor.getSchemeName(); 1252 if( !aFillProperties.maFillColor.isPlaceHolder() && !sColorFillScheme.isEmpty() ) 1253 { 1254 aProperties.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClr", sColorFillScheme)); 1255 aProperties.push_back(comphelper::makePropertyValue("SpPrSolidFillSchemeClrTransformations", aFillProperties.maFillColor.getTransformations())); 1256 } 1257 OUString sLnColorFillScheme = aLineProperties.maLineFill.maFillColor.getSchemeName(); 1258 if( !aLineProperties.maLineFill.maFillColor.isPlaceHolder() && !sLnColorFillScheme.isEmpty() ) 1259 { 1260 aProperties.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClr", sLnColorFillScheme)); 1261 aProperties.push_back(comphelper::makePropertyValue("SpPrLnSolidFillSchemeClrTransformations", aLineProperties.maLineFill.maFillColor.getTransformations())); 1262 } 1263 putPropertiesToGrabBag(comphelper::containerToSequence(aProperties)); 1264 1265 // Store original gradient fill of the shape to InteropGrabBag 1266 // LibreOffice doesn't support all the kinds of gradient so we save its complete definition 1267 if( aShapeProps.hasProperty( PROP_FillGradient ) ) 1268 { 1269 std::vector<beans::PropertyValue> aGradientStops; 1270 size_t i = 0; 1271 for( const auto& [rPos, rColor] : aFillProperties.maGradientProps.maGradientStops ) 1272 { // for each stop in the gradient definition: 1273 1274 // save position 1275 std::vector<beans::PropertyValue> aGradientStop; 1276 aGradientStop.push_back(comphelper::makePropertyValue("Pos", rPos)); 1277 1278 OUString sStopColorScheme = rColor.getSchemeName(); 1279 if( sStopColorScheme.isEmpty() ) 1280 { 1281 // save RGB color 1282 aGradientStop.push_back(comphelper::makePropertyValue("RgbClr", rColor.getColor(rGraphicHelper, nFillPhClr))); 1283 // in the case of a RGB color, transformations are already applied to 1284 // the color with the exception of alpha transformations. We only need 1285 // to keep the transparency value to calculate the alpha value later. 1286 if( rColor.hasTransparency() ) 1287 aGradientStop.push_back(comphelper::makePropertyValue("Transparency", rColor.getTransparency())); 1288 } 1289 else 1290 { 1291 // save color with scheme name 1292 aGradientStop.push_back(comphelper::makePropertyValue("SchemeClr", sStopColorScheme)); 1293 // save all color transformations 1294 aGradientStop.push_back(comphelper::makePropertyValue("Transformations", rColor.getTransformations())); 1295 } 1296 1297 aGradientStops.push_back(comphelper::makePropertyValue(OUString::number(i), comphelper::containerToSequence(aGradientStop))); 1298 ++i; 1299 } 1300 // If getFillProperties.moFillType is unused that means gradient is defined by a theme 1301 // which is already saved into StyleFillRef property, so no need to save the explicit values too 1302 if( getFillProperties().moFillType.has() ) 1303 putPropertyToGrabBag( "GradFillDefinition", uno::Any(comphelper::containerToSequence(aGradientStops))); 1304 putPropertyToGrabBag( "OriginalGradFill", aShapeProps.getProperty(PROP_FillGradient) ); 1305 } 1306 1307 // store unsupported effect attributes in the grab bag 1308 if (!aEffectProperties.m_Effects.empty()) 1309 { 1310 std::vector<beans::PropertyValue> aEffects; 1311 sal_uInt32 i = 0; 1312 for (auto const& it : aEffectProperties.m_Effects) 1313 { 1314 PropertyValue aEffect = it->getEffect(); 1315 if( !aEffect.Name.isEmpty() ) 1316 { 1317 std::vector<beans::PropertyValue> aEffectsGrabBag; 1318 aEffectsGrabBag.push_back(comphelper::makePropertyValue("Attribs", aEffect.Value)); 1319 1320 Color& aColor( it->moColor ); 1321 OUString sColorScheme = aColor.getSchemeName(); 1322 if( sColorScheme.isEmpty() ) 1323 { 1324 // RGB color and transparency value 1325 aEffectsGrabBag.push_back(comphelper::makePropertyValue("RgbClr", aColor.getColor(rGraphicHelper, nFillPhClr))); 1326 aEffectsGrabBag.push_back(comphelper::makePropertyValue("RgbClrTransparency", aColor.getTransparency())); 1327 } 1328 else 1329 { 1330 // scheme color with name and transformations 1331 aEffectsGrabBag.push_back(comphelper::makePropertyValue("SchemeClr", sColorScheme)); 1332 aEffectsGrabBag.push_back(comphelper::makePropertyValue("SchemeClrTransformations", aColor.getTransformations())); 1333 } 1334 aEffects.push_back(comphelper::makePropertyValue(aEffect.Name, comphelper::containerToSequence(aEffectsGrabBag))); 1335 ++i; 1336 } 1337 } 1338 putPropertyToGrabBag("EffectProperties", uno::Any(comphelper::containerToSequence(aEffects))); 1339 } 1340 1341 // add 3D effects if any 1342 Sequence< PropertyValue > aCamera3DEffects = get3DProperties().getCameraAttributes(); 1343 Sequence< PropertyValue > aLightRig3DEffects = get3DProperties().getLightRigAttributes(); 1344 Sequence< PropertyValue > aShape3DEffects = get3DProperties().getShape3DAttributes( rGraphicHelper, nFillPhClr ); 1345 if( aCamera3DEffects.hasElements() || aLightRig3DEffects.hasElements() || aShape3DEffects.hasElements() ) 1346 { 1347 uno::Sequence<beans::PropertyValue> a3DEffectsGrabBag = comphelper::InitPropertySequence( 1348 { 1349 {"Camera", uno::makeAny(aCamera3DEffects)}, 1350 {"LightRig", uno::makeAny(aLightRig3DEffects)}, 1351 {"Shape3D", uno::makeAny(aShape3DEffects)} 1352 }); 1353 putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag ) ); 1354 } 1355 1356 // store bitmap artistic effects in the grab bag 1357 if( !mpGraphicPropertiesPtr->maBlipProps.maEffect.isEmpty() ) 1358 putPropertyToGrabBag( "ArtisticEffectProperties", 1359 Any( mpGraphicPropertiesPtr->maBlipProps.maEffect.getEffect() ) ); 1360 } 1361 1362 else if( mbLockedCanvas ) 1363 { 1364 //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas 1365 putPropertyToGrabBag( "LockedCanvas", Any( true ) ); 1366 } 1367 1368 // These can have a custom geometry, so position should be set here, 1369 // after creation but before custom shape handling, using the position 1370 // we got from the caller. 1371 if (mbWps && aServiceName == "com.sun.star.drawing.LineShape") 1372 mxShape->setPosition(maPosition); 1373 1374 if( bIsCustomShape ) 1375 { 1376 if ( mbFlipH ) 1377 mpCustomShapePropertiesPtr->setMirroredX( true ); 1378 if ( mbFlipV ) 1379 mpCustomShapePropertiesPtr->setMirroredY( true ); 1380 if( getTextBody() ) 1381 { 1382 sal_Int32 nTextCameraZRotation = static_cast< sal_Int32 >( get3DProperties().maCameraRotation.mnRevolution.get() ); 1383 mpCustomShapePropertiesPtr->setTextCameraZRotateAngle( nTextCameraZRotation / 60000 ); 1384 1385 sal_Int32 nTextRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moRotation.get( 0 ) ); 1386 1387 nTextRotateAngle -= mnDiagramRotation; 1388 /* OOX measures text rotation clockwise in 1/60000th degrees, 1389 relative to the containing shape. setTextRotateAngle wants 1390 degrees anticlockwise. */ 1391 mpCustomShapePropertiesPtr->setTextRotateAngle( -1 * nTextRotateAngle / 60000 ); 1392 } 1393 1394 // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks 1395 // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs 1396 SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName << "'"); 1397 SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName << "'"); 1398 mpCustomShapePropertiesPtr->pushToPropSet( xSet, mxShape, maSize ); 1399 1400 if (mpTextBody) 1401 { 1402 bool bIsPresetShape = !mpTextBody->getTextProperties().msPrst.isEmpty(); 1403 if (bIsPresetShape) 1404 { 1405 OUString sClass; 1406 const OUString sPresetType = mpTextBody->getTextProperties().msPrst; 1407 sClass = PresetGeometryTypeNames::GetFontworkType( sPresetType ); 1408 1409 lcl_createPresetShape( mxShape, sClass, sPresetType, mpCustomShapePropertiesPtr, mpTextBody, rGraphicHelper ); 1410 } 1411 } 1412 } 1413 else if( getTextBody() ) 1414 getTextBody()->getTextProperties().pushVertSimulation(); 1415 1416 PropertySet aPropertySet(mxShape); 1417 if ( !bUseRotationTransform && mnRotation != 0 ) 1418 { 1419 // use the same logic for rotation from VML exporter (SimpleShape::implConvertAndInsert at vmlshape.cxx) 1420 aPropertySet.setAnyProperty( PROP_RotateAngle, makeAny( sal_Int32( NormAngle36000( mnRotation / -600 ) ) ) ); 1421 aPropertySet.setAnyProperty( PROP_HoriOrientPosition, makeAny( maPosition.X ) ); 1422 aPropertySet.setAnyProperty( PROP_VertOrientPosition, makeAny( maPosition.Y ) ); 1423 } 1424 1425 // in some cases, we don't have any text body. 1426 if( getTextBody() && ( !bDoNotInsertEmptyTextBody || !mpTextBody->isEmpty() ) ) 1427 { 1428 Reference < XText > xText( mxShape, UNO_QUERY ); 1429 if ( xText.is() ) // not every shape is supporting an XText interface (e.g. GroupShape) 1430 { 1431 TextCharacterProperties aCharStyleProperties; 1432 if( const ShapeStyleRef* pFontRef = getShapeStyleRef( XML_fontRef ) ) 1433 { 1434 if( pFontRef->mnThemedIdx != 0 ) 1435 { 1436 if( pTheme ) 1437 if( const TextCharacterProperties* pCharProps = pTheme->getFontStyle( pFontRef->mnThemedIdx ) ) 1438 aCharStyleProperties.assignUsed( *pCharProps ); 1439 SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color"); 1440 if ( pFontRef->maPhClr.isUsed() ) 1441 { 1442 aCharStyleProperties.maFillProperties.maFillColor = pFontRef->maPhClr; 1443 aCharStyleProperties.maFillProperties.moFillType.set(XML_solidFill); 1444 } 1445 } 1446 } 1447 xText->setString(""); 1448 Reference < XTextCursor > xAt = xText->createTextCursor(); 1449 getTextBody()->insertAt( rFilterBase, xText, xAt, aCharStyleProperties, mpMasterTextListStyle ); 1450 } 1451 } 1452 else if (mbTextBox) 1453 { 1454 // No drawingML text, but WPS text is expected: save the theme 1455 // character color on the shape, then. 1456 if(const ShapeStyleRef* pFontRef = getShapeStyleRef(XML_fontRef)) 1457 { 1458 ::Color nCharColor = pFontRef->maPhClr.getColor(rGraphicHelper); 1459 aPropertySet.setAnyProperty(PROP_CharColor, uno::makeAny(nCharColor)); 1460 } 1461 } 1462 1463 // Set glow effect properties 1464 if ( aEffectProperties.maGlow.moGlowRad.has() ) 1465 { 1466 uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY); 1467 propertySet->setPropertyValue("GlowEffectRadius", makeAny(convertEmuToHmm(aEffectProperties.maGlow.moGlowRad.get()))); 1468 propertySet->setPropertyValue("GlowEffectColor", makeAny(aEffectProperties.maGlow.moGlowColor.getColor(rGraphicHelper))); 1469 propertySet->setPropertyValue("GlowEffectTransparency", makeAny(aEffectProperties.maGlow.moGlowColor.getTransparency())); 1470 } 1471 1472 // Set soft edge effect properties 1473 if (aEffectProperties.maSoftEdge.moRad.has()) 1474 { 1475 uno::Reference<beans::XPropertySet> propertySet(mxShape, uno::UNO_QUERY); 1476 propertySet->setPropertyValue( 1477 "SoftEdgeRadius", makeAny(convertEmuToHmm(aEffectProperties.maSoftEdge.moRad.get()))); 1478 } 1479 } 1480 1481 if( mxShape.is() ) 1482 finalizeXShape( rFilterBase, rxShapes ); 1483 1484 return mxShape; 1485 } 1486 1487 void Shape::keepDiagramDrawing(XmlFilterBase& rFilterBase, const OUString& rFragmentPath) 1488 { 1489 uno::Sequence<uno::Any> diagramDrawing(2); 1490 // drawingValue[0] => dom, drawingValue[1] => Sequence of associated relationships 1491 1492 sal_Int32 length = maDiagramDoms.getLength(); 1493 maDiagramDoms.realloc(length + 1); 1494 1495 diagramDrawing[0] <<= rFilterBase.importFragment(rFragmentPath); 1496 diagramDrawing[1] <<= resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, "image"); 1497 1498 beans::PropertyValue* pValue = maDiagramDoms.getArray(); 1499 pValue[length].Name = "OOXDrawing"; 1500 pValue[length].Value <<= diagramDrawing; 1501 } 1502 1503 void Shape::keepDiagramCompatibilityInfo() 1504 { 1505 try 1506 { 1507 if( !maDiagramDoms.hasElements() ) 1508 return; 1509 1510 Reference < XPropertySet > xSet( mxShape, UNO_QUERY_THROW ); 1511 Reference < XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); 1512 if ( !xSetInfo.is() ) 1513 return; 1514 1515 if (mpDiagramData) 1516 { 1517 if (SdrObject* pObj = GetSdrObjectFromXShape(mxShape)) 1518 pObj->SetDiagramData(mpDiagramData); 1519 } 1520 1521 const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1522 if( !xSetInfo->hasPropertyByName( aGrabBagPropName ) ) 1523 return; 1524 1525 Sequence < PropertyValue > aGrabBag; 1526 xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; 1527 1528 // We keep the previous items, if present 1529 if ( aGrabBag.hasElements() ) 1530 xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, maDiagramDoms) ) ); 1531 else 1532 xSet->setPropertyValue( aGrabBagPropName, Any( maDiagramDoms ) ); 1533 } 1534 catch( const Exception& ) 1535 { 1536 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::keepDiagramCompatibilityInfo" ); 1537 } 1538 } 1539 1540 void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase) 1541 { 1542 try 1543 { 1544 Reference<XPropertySet> xSet(mxShape, UNO_QUERY_THROW); 1545 1546 xSet->setPropertyValue("MoveProtect", Any(true)); 1547 xSet->setPropertyValue("SizeProtect", Any(true)); 1548 1549 // Replace existing shapes with a new Graphic Object rendered 1550 // from them 1551 Reference<XShape> xShape(renderDiagramToGraphic(rFilterBase)); 1552 Reference<XShapes> xShapes(mxShape, UNO_QUERY_THROW); 1553 while (xShapes->hasElements()) 1554 xShapes->remove(Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW)); 1555 xShapes->add(xShape); 1556 } 1557 catch (const Exception&) 1558 { 1559 TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile"); 1560 } 1561 } 1562 1563 Reference < XShape > Shape::renderDiagramToGraphic( XmlFilterBase const & rFilterBase ) 1564 { 1565 Reference< XShape > xShape; 1566 1567 try 1568 { 1569 if( !maDiagramDoms.hasElements() ) 1570 return xShape; 1571 1572 // Stream in which to place the rendered shape 1573 SvMemoryStream aTempStream; 1574 Reference < io::XStream > xStream( new utl::OStreamWrapper( aTempStream ) ); 1575 Reference < io::XOutputStream > xOutputStream( xStream->getOutputStream() ); 1576 1577 // Size of the rendering 1578 awt::Size aActualSize = mxShape->getSize(); 1579 Size aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM))); 1580 double fPixelsPer100thmm = static_cast < double > ( aResolution.Width() ) / 100000.0; 1581 awt::Size aSize( static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Width ) + 0.5 ), 1582 static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Height ) + 0.5 ) ); 1583 1584 Sequence< PropertyValue > aFilterData( 4 ); 1585 aFilterData[ 0 ].Name = "PixelWidth"; 1586 aFilterData[ 0 ].Value <<= aSize.Width; 1587 aFilterData[ 1 ].Name = "PixelHeight"; 1588 aFilterData[ 1 ].Value <<= aSize.Height; 1589 aFilterData[ 2 ].Name = "LogicalWidth"; 1590 aFilterData[ 2 ].Value <<= aActualSize.Width; 1591 aFilterData[ 3 ].Name = "LogicalHeight"; 1592 aFilterData[ 3 ].Value <<= aActualSize.Height; 1593 1594 Sequence < PropertyValue > aDescriptor( 3 ); 1595 aDescriptor[ 0 ].Name = "OutputStream"; 1596 aDescriptor[ 0 ].Value <<= xOutputStream; 1597 aDescriptor[ 1 ].Name = "FilterName"; 1598 aDescriptor[ 1 ].Value <<= OUString("SVM"); // Rendering format 1599 aDescriptor[ 2 ].Name = "FilterData"; 1600 aDescriptor[ 2 ].Value <<= aFilterData; 1601 1602 Reference < lang::XComponent > xSourceDoc( mxShape, UNO_QUERY_THROW ); 1603 Reference < XGraphicExportFilter > xGraphicExporter = GraphicExportFilter::create( rFilterBase.getComponentContext() ); 1604 xGraphicExporter->setSourceDocument( xSourceDoc ); 1605 xGraphicExporter->filter( aDescriptor ); 1606 1607 aTempStream.Seek( STREAM_SEEK_TO_BEGIN ); 1608 1609 Graphic aGraphic; 1610 GraphicFilter aFilter( false ); 1611 if ( aFilter.ImportGraphic( aGraphic, "", aTempStream, GRFILTER_FORMAT_NOTFOUND, nullptr, GraphicFilterImportFlags::NONE, static_cast < Sequence < PropertyValue >* > ( nullptr ) ) != ERRCODE_NONE ) 1612 { 1613 SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" ); 1614 return xShape; 1615 } 1616 1617 Reference < graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() ); 1618 Reference < lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW ); 1619 xShape.set( xServiceFact->createInstance( "com.sun.star.drawing.GraphicObjectShape" ), UNO_QUERY_THROW ); 1620 Reference < XPropertySet > xPropSet( xShape, UNO_QUERY_THROW ); 1621 xPropSet->setPropertyValue( "Graphic", Any( xGraphic ) ); 1622 xPropSet->setPropertyValue( "MoveProtect", Any( true ) ); 1623 xPropSet->setPropertyValue( "SizeProtect", Any( true ) ); 1624 xPropSet->setPropertyValue( "Name", Any( OUString( "RenderedShapes" ) ) ); 1625 } 1626 catch( const Exception& ) 1627 { 1628 TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" ); 1629 } 1630 1631 return xShape; 1632 } 1633 1634 void Shape::setTextBody(const TextBodyPtr & pTextBody) 1635 { 1636 mpTextBody = pTextBody; 1637 } 1638 1639 void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle ) 1640 { 1641 SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId << "'"); 1642 1643 mpMasterTextListStyle = pMasterTextListStyle; 1644 } 1645 1646 OUString Shape::finalizeServiceName( XmlFilterBase& rFilter, const OUString& rServiceName, const awt::Rectangle& rShapeRect ) 1647 { 1648 OUString aServiceName = rServiceName; 1649 switch( meFrameType ) 1650 { 1651 case FRAMETYPE_OLEOBJECT: 1652 { 1653 awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height ); 1654 if( rFilter.getOleObjectHelper().importOleObject( maShapeProperties, *mxOleObjectInfo, aOleSize ) ) 1655 aServiceName = "com.sun.star.drawing.OLE2Shape"; 1656 1657 // get the path to the representation graphic 1658 OUString aGraphicPath; 1659 if( !mxOleObjectInfo->maShapeId.isEmpty() ) 1660 if( ::oox::vml::Drawing* pVmlDrawing = rFilter.getVmlDrawing() ) 1661 if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId ) ) 1662 aGraphicPath = pVmlShape->getGraphicPath(); 1663 1664 // import and store the graphic 1665 if( !aGraphicPath.isEmpty() ) 1666 { 1667 // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF) 1668 WmfExternal aExtHeader; 1669 aExtHeader.mapMode = 8; // MM_ANISOTROPIC 1670 aExtHeader.xExt = rShapeRect.Width; 1671 aExtHeader.yExt = rShapeRect.Height; 1672 1673 Reference< graphic::XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath, &aExtHeader ); 1674 if( xGraphic.is() ) 1675 maShapeProperties.setProperty(PROP_Graphic, xGraphic); 1676 } 1677 } 1678 break; 1679 1680 default:; 1681 } 1682 return aServiceName; 1683 } 1684 1685 void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes ) 1686 { 1687 switch( meFrameType ) 1688 { 1689 case FRAMETYPE_CHART: 1690 { 1691 OSL_ENSURE( !mxChartShapeInfo->maFragmentPath.isEmpty(), "Shape::finalizeXShape - missing chart fragment" ); 1692 if( mxShape.is() && !mxChartShapeInfo->maFragmentPath.isEmpty() ) try 1693 { 1694 // set the chart2 OLE class ID at the OLE shape 1695 PropertySet aShapeProp( mxShape ); 1696 aShapeProp.setProperty( PROP_CLSID, OUString( "12dcae26-281f-416f-a234-c3086127382e" ) ); 1697 1698 // get the XModel interface of the embedded object from the OLE shape 1699 Reference< frame::XModel > xDocModel; 1700 aShapeProp.getProperty( xDocModel, PROP_Model ); 1701 Reference< chart2::XChartDocument > xChartDoc( xDocModel, UNO_QUERY_THROW ); 1702 1703 // load the chart data from the XML fragment 1704 bool bMSO2007Doc = rFilter.isMSO2007Document(); 1705 chart::ChartSpaceModel aModel(bMSO2007Doc); 1706 chart::ChartSpaceFragment *pChartSpaceFragment = new chart::ChartSpaceFragment( 1707 rFilter, mxChartShapeInfo->maFragmentPath, aModel ); 1708 const OUString aThemeOverrideFragmentPath( pChartSpaceFragment-> 1709 getFragmentPathFromFirstTypeFromOfficeDoc("themeOverride") ); 1710 rFilter.importFragment( pChartSpaceFragment ); 1711 ::oox::ppt::PowerPointImport *pPowerPointImport = 1712 dynamic_cast< ::oox::ppt::PowerPointImport* >(&rFilter); 1713 if (!aThemeOverrideFragmentPath.isEmpty() && pPowerPointImport) 1714 { 1715 uno::Reference< xml::sax::XFastSAXSerializable > xDoc( 1716 rFilter.importFragment(aThemeOverrideFragmentPath), uno::UNO_QUERY_THROW); 1717 ThemePtr pTheme = pPowerPointImport->getActualSlidePersist()->getTheme(); 1718 rFilter.importFragment(new ThemeOverrideFragmentHandler( 1719 rFilter, aThemeOverrideFragmentPath, *pTheme), xDoc); 1720 pPowerPointImport->getActualSlidePersist()->setTheme(pTheme); 1721 } 1722 1723 // convert imported chart model to chart document 1724 Reference< drawing::XShapes > xExternalPage; 1725 if( !mxChartShapeInfo->mbEmbedShapes ) 1726 xExternalPage = rxShapes; 1727 if( rFilter.getChartConverter() ) 1728 { 1729 rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() ); 1730 if( !xChartDoc->hasInternalDataProvider() ) 1731 { 1732 Reference< chart2::data::XDataReceiver > xDataRec( xChartDoc, UNO_QUERY ); 1733 Reference< chart2::data::XDataSource > xData = xDataRec->getUsedData(); 1734 if( !xData->getDataSequences().hasElements() || !xData->getDataSequences()[0]->getValues().is() || 1735 !xData->getDataSequences()[0]->getValues()->getData().hasElements() ) 1736 { 1737 rFilter.useInternalChartDataTable( true ); 1738 rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() ); 1739 rFilter.useInternalChartDataTable( false ); 1740 } 1741 } 1742 1743 } 1744 } 1745 catch( Exception& ) 1746 { 1747 } 1748 } 1749 break; 1750 1751 default:; 1752 } 1753 } 1754 1755 void Shape::putPropertyToGrabBag( const OUString& sPropertyName, const Any& aPropertyValue ) 1756 { 1757 PropertyValue aNewProperty; 1758 aNewProperty.Name = sPropertyName; 1759 aNewProperty.Value = aPropertyValue; 1760 putPropertyToGrabBag( aNewProperty ); 1761 } 1762 1763 void Shape::putPropertyToGrabBag( const PropertyValue& pProperty ) 1764 { 1765 Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); 1766 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); 1767 const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1768 if( mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName ) ) 1769 { 1770 Sequence< PropertyValue > aGrabBag; 1771 xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; 1772 1773 sal_Int32 length = aGrabBag.getLength(); 1774 aGrabBag.realloc( length + 1 ); 1775 aGrabBag[length] = pProperty; 1776 1777 xSet->setPropertyValue( aGrabBagPropName, Any( aGrabBag ) ); 1778 } 1779 } 1780 1781 void Shape::putPropertiesToGrabBag( const Sequence< PropertyValue >& aProperties ) 1782 { 1783 Reference< XPropertySet > xSet( mxShape, UNO_QUERY ); 1784 Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() ); 1785 const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; 1786 if( !(mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName )) ) 1787 return; 1788 1789 // get existing grab bag 1790 Sequence< PropertyValue > aGrabBag; 1791 xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; 1792 1793 std::vector<PropertyValue> aVec; 1794 aVec.reserve(aProperties.getLength()); 1795 1796 // put the new items 1797 std::transform(aProperties.begin(), aProperties.end(), std::back_inserter(aVec), 1798 [](const PropertyValue& rProp) { 1799 PropertyValue aProp; 1800 aProp.Name = rProp.Name; 1801 aProp.Value = rProp.Value; 1802 return aProp; 1803 }); 1804 1805 // put it back to the shape 1806 xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, aVec) ) ); 1807 } 1808 1809 FillProperties Shape::getActualFillProperties(const Theme* pTheme, const FillProperties* pParentShapeFillProps) const 1810 { 1811 FillProperties aFillProperties; 1812 aFillProperties.moFillType = XML_noFill; 1813 1814 // Reference shape properties 1815 aFillProperties.assignUsed( *mpShapeRefFillPropPtr ); 1816 1817 // Theme 1818 if( pTheme != nullptr ) 1819 { 1820 if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) ) 1821 { 1822 if( const FillProperties* pFillProps = pTheme->getFillStyle( pFillRef->mnThemedIdx ) ) 1823 aFillProperties.assignUsed( *pFillProps ); 1824 } 1825 } 1826 1827 // Properties specified directly for this shape 1828 aFillProperties.assignUsed(getFillProperties()); 1829 1830 // Parent shape's properties 1831 if ( pParentShapeFillProps != nullptr) 1832 if( getFillProperties().moFillType.has() && getFillProperties().moFillType.get() == XML_grpFill ) 1833 aFillProperties.assignUsed( *pParentShapeFillProps ); 1834 1835 return aFillProperties; 1836 } 1837 1838 LineProperties Shape::getActualLineProperties(const Theme* pTheme) const 1839 { 1840 LineProperties aLineProperties; 1841 aLineProperties.maLineFill.moFillType = XML_noFill; 1842 1843 // Reference shape properties 1844 aLineProperties.assignUsed( *mpShapeRefLinePropPtr ); 1845 1846 // Theme 1847 if( pTheme != nullptr ) 1848 { 1849 if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) ) 1850 { 1851 if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) ) 1852 aLineProperties.assignUsed( *pLineProps ); 1853 } 1854 } 1855 1856 // Properties specified directly for this shape 1857 aLineProperties.assignUsed( getLineProperties() ); 1858 1859 return aLineProperties; 1860 } 1861 1862 EffectProperties Shape::getActualEffectProperties(const Theme* pTheme) const 1863 { 1864 EffectProperties aEffectProperties; 1865 1866 // Reference shape properties 1867 aEffectProperties.assignUsed( *mpShapeRefEffectPropPtr ); 1868 1869 // Theme 1870 if( pTheme != nullptr ) 1871 { 1872 if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) ) 1873 { 1874 if( const EffectProperties* pEffectProps = pTheme->getEffectStyle( pEffectRef->mnThemedIdx ) ) 1875 aEffectProperties.assignUsed( *pEffectProps ); 1876 } 1877 } 1878 1879 // Properties specified directly for this shape 1880 aEffectProperties.assignUsed ( getEffectProperties() ); 1881 1882 return aEffectProperties; 1883 } 1884 1885 uno::Sequence< uno::Sequence< uno::Any > > Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase& rFilter, const OUString& sFragment, const OUString& sType ) 1886 { 1887 uno::Sequence< uno::Sequence< uno::Any > > xRelListTemp; 1888 sal_Int32 counter = 0; 1889 1890 core::RelationsRef xRels = rFilter.importRelations( sFragment ); 1891 if ( xRels ) 1892 { 1893 core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc( sType ); 1894 if ( xImageRels ) 1895 { 1896 xRelListTemp.realloc( xImageRels->size() ); 1897 for (auto const& imageRel : *xImageRels) 1898 { 1899 uno::Sequence< uno::Any > diagramRelTuple (3); 1900 // [0] => RID, [1] => InputStream [2] => extension 1901 OUString sRelId = imageRel.second.maId; 1902 1903 diagramRelTuple[0] <<= sRelId; 1904 OUString sTarget = xImageRels->getFragmentPathFromRelId( sRelId ); 1905 1906 uno::Reference< io::XInputStream > xImageInputStrm( rFilter.openInputStream( sTarget ), uno::UNO_SET_THROW ); 1907 StreamDataSequence dataSeq; 1908 if ( rFilter.importBinaryData( dataSeq, sTarget ) ) 1909 { 1910 diagramRelTuple[1] <<= dataSeq; 1911 } 1912 1913 diagramRelTuple[2] <<= sTarget.copy( sTarget.lastIndexOf(".") ); 1914 1915 xRelListTemp[counter] = diagramRelTuple; 1916 ++counter; 1917 } 1918 xRelListTemp.realloc(counter); 1919 1920 } 1921 } 1922 return xRelListTemp; 1923 } 1924 1925 void Shape::cloneFillProperties() 1926 { 1927 auto pFillProperties = std::make_shared<FillProperties>(); 1928 pFillProperties->assignUsed(*mpFillPropertiesPtr); 1929 mpFillPropertiesPtr = pFillProperties; 1930 } 1931 } 1932 1933 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1934
