1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/vml/vmlshape.hxx" 29 30 #include <com/sun/star/beans/PropertyValues.hpp> 31 #include <com/sun/star/awt/XControlModel.hpp> 32 #include <com/sun/star/drawing/PointSequenceSequence.hpp> 33 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> 34 #include <com/sun/star/drawing/XShapes.hpp> 35 #include <com/sun/star/graphic/XGraphic.hpp> 36 #include <rtl/math.hxx> 37 #include <rtl/ustrbuf.hxx> 38 #include "oox/core/xmlfilterbase.hxx" 39 #include "oox/drawingml/shapepropertymap.hxx" 40 #include "oox/helper/containerhelper.hxx" 41 #include "oox/helper/graphichelper.hxx" 42 #include "oox/helper/propertyset.hxx" 43 #include "oox/ole/axcontrol.hxx" 44 #include "oox/ole/axcontrolfragment.hxx" 45 #include "oox/ole/oleobjecthelper.hxx" 46 #include "oox/vml/vmldrawing.hxx" 47 #include "oox/vml/vmlshapecontainer.hxx" 48 #include "oox/vml/vmltextbox.hxx" 49 50 namespace oox { 51 namespace vml { 52 53 // ============================================================================ 54 55 using namespace ::com::sun::star::awt; 56 using namespace ::com::sun::star::drawing; 57 using namespace ::com::sun::star::graphic; 58 using namespace ::com::sun::star::uno; 59 60 using ::oox::core::XmlFilterBase; 61 using ::rtl::OUString; 62 using ::rtl::OUStringBuffer; 63 64 // ============================================================================ 65 66 namespace { 67 68 const sal_Int32 VML_SHAPETYPE_PICTUREFRAME = 75; 69 const sal_Int32 VML_SHAPETYPE_HOSTCONTROL = 201; 70 71 // ---------------------------------------------------------------------------- 72 73 Point lclGetAbsPoint( const Point& rRelPoint, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) 74 { 75 double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; 76 double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; 77 Point aAbsPoint; 78 aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 ); 79 aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 ); 80 return aAbsPoint; 81 } 82 83 Rectangle lclGetAbsRect( const Rectangle& rRelRect, const Rectangle& rShapeRect, const Rectangle& rCoordSys ) 84 { 85 double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width; 86 double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height; 87 Rectangle aAbsRect; 88 aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 ); 89 aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 ); 90 aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 ); 91 aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 ); 92 return aAbsRect; 93 } 94 95 } // namespace 96 97 // ============================================================================ 98 99 ShapeTypeModel::ShapeTypeModel() 100 { 101 } 102 103 void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource ) 104 { 105 moShapeType.assignIfUsed( rSource.moShapeType ); 106 moCoordPos.assignIfUsed( rSource.moCoordPos ); 107 moCoordSize.assignIfUsed( rSource.moCoordSize ); 108 /* The style properties position, left, top, width, height, margin-left, 109 margin-top are not derived from shape template to shape. */ 110 maStrokeModel.assignUsed( rSource.maStrokeModel ); 111 maFillModel.assignUsed( rSource.maFillModel ); 112 moGraphicPath.assignIfUsed( rSource.moGraphicPath ); 113 moGraphicTitle.assignIfUsed( rSource.moGraphicTitle ); 114 } 115 116 // ---------------------------------------------------------------------------- 117 118 ShapeType::ShapeType( Drawing& rDrawing ) : 119 mrDrawing( rDrawing ) 120 { 121 } 122 123 ShapeType::~ShapeType() 124 { 125 } 126 127 sal_Int32 ShapeType::getShapeType() const 128 { 129 return maTypeModel.moShapeType.get( 0 ); 130 } 131 132 OUString ShapeType::getGraphicPath() const 133 { 134 return maTypeModel.moGraphicPath.get( OUString() ); 135 } 136 137 Rectangle ShapeType::getCoordSystem() const 138 { 139 Int32Pair aCoordPos = maTypeModel.moCoordPos.get( Int32Pair( 0, 0 ) ); 140 Int32Pair aCoordSize = maTypeModel.moCoordSize.get( Int32Pair( 1000, 1000 ) ); 141 return Rectangle( aCoordPos.first, aCoordPos.second, aCoordSize.first, aCoordSize.second ); 142 } 143 144 Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const 145 { 146 return pParentAnchor ? 147 lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) : 148 getAbsRectangle(); 149 } 150 151 Rectangle ShapeType::getAbsRectangle() const 152 { 153 const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); 154 return Rectangle( 155 ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maLeft, 0, true, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true ), 156 ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginTop, 0, false, true ), 157 ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maWidth, 0, true, true ), 158 ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true ) ); 159 } 160 161 Rectangle ShapeType::getRelRectangle() const 162 { 163 return Rectangle( 164 maTypeModel.maLeft.toInt32(), 165 maTypeModel.maTop.toInt32(), 166 maTypeModel.maWidth.toInt32(), 167 maTypeModel.maHeight.toInt32() ); 168 } 169 170 // ============================================================================ 171 172 ClientData::ClientData() : 173 mnObjType( XML_TOKEN_INVALID ), 174 mnTextHAlign( XML_Left ), 175 mnTextVAlign( XML_Top ), 176 mnCol( -1 ), 177 mnRow( -1 ), 178 mnChecked( VML_CLIENTDATA_UNCHECKED ), 179 mnDropStyle( XML_Combo ), 180 mnDropLines( 1 ), 181 mnVal( 0 ), 182 mnMin( 0 ), 183 mnMax( 0 ), 184 mnInc( 0 ), 185 mnPage( 0 ), 186 mnSelType( XML_Single ), 187 mnVTEdit( VML_CLIENTDATA_TEXT ), 188 mbPrintObject( true ), 189 mbVisible( false ), 190 mbDde( false ), 191 mbNo3D( false ), 192 mbNo3D2( false ), 193 mbMultiLine( false ), 194 mbVScroll( false ), 195 mbSecretEdit( false ) 196 { 197 } 198 199 // ---------------------------------------------------------------------------- 200 201 ShapeModel::ShapeModel() 202 { 203 } 204 205 ShapeModel::~ShapeModel() 206 { 207 } 208 209 TextBox& ShapeModel::createTextBox() 210 { 211 mxTextBox.reset( new TextBox ); 212 return *mxTextBox; 213 } 214 215 ClientData& ShapeModel::createClientData() 216 { 217 mxClientData.reset( new ClientData ); 218 return *mxClientData; 219 } 220 221 // ---------------------------------------------------------------------------- 222 223 ShapeBase::ShapeBase( Drawing& rDrawing ) : 224 ShapeType( rDrawing ) 225 { 226 } 227 228 void ShapeBase::finalizeFragmentImport() 229 { 230 // resolve shape template reference 231 if( (maShapeModel.maType.getLength() > 1) && (maShapeModel.maType[ 0 ] == '#') ) 232 if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( maShapeModel.maType.copy( 1 ), true ) ) 233 maTypeModel.assignUsed( pShapeType->getTypeModel() ); 234 } 235 236 OUString ShapeBase::getShapeName() const 237 { 238 if( maTypeModel.maShapeName.getLength() > 0 ) 239 return maTypeModel.maShapeName; 240 241 OUString aBaseName = mrDrawing.getShapeBaseName( *this ); 242 if( aBaseName.getLength() > 0 ) 243 { 244 sal_Int32 nShapeIdx = mrDrawing.getLocalShapeIndex( getShapeId() ); 245 if( nShapeIdx > 0 ) 246 return OUStringBuffer( aBaseName ).append( sal_Unicode( ' ' ) ).append( nShapeIdx ).makeStringAndClear(); 247 } 248 249 return OUString(); 250 } 251 252 const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const 253 { 254 return 0; 255 } 256 257 const ShapeBase* ShapeBase::getChildById( const OUString& ) const 258 { 259 return 0; 260 } 261 262 Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const 263 { 264 Reference< XShape > xShape; 265 if( mrDrawing.isShapeSupported( *this ) ) 266 { 267 /* Calculate shape rectangle. Applications may do something special 268 according to some imported shape client data (e.g. Excel cell anchor). */ 269 Rectangle aShapeRect = calcShapeRectangle( pParentAnchor ); 270 271 // convert the shape, if the calculated rectangle is not empty 272 if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() ) 273 { 274 xShape = implConvertAndInsert( rxShapes, aShapeRect ); 275 if( xShape.is() ) 276 { 277 // set imported or generated shape name (not supported by form controls) 278 PropertySet aShapeProp( xShape ); 279 if( aShapeProp.hasProperty( PROP_Name ) ) 280 aShapeProp.setProperty( PROP_Name, getShapeName() ); 281 282 /* Notify the drawing that a new shape has been inserted. For 283 convenience, pass the rectangle that contains position and 284 size of the shape. */ 285 bool bGroupChild = pParentAnchor != 0; 286 mrDrawing.notifyXShapeInserted( xShape, aShapeRect, *this, bGroupChild ); 287 } 288 } 289 } 290 return xShape; 291 } 292 293 void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const 294 { 295 if( rxShape.is() ) 296 { 297 /* Calculate shape rectangle. Applications may do something special 298 according to some imported shape client data (e.g. Excel cell anchor). */ 299 Rectangle aShapeRect = calcShapeRectangle( pParentAnchor ); 300 301 // convert the shape, if the calculated rectangle is not empty 302 if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) ) 303 { 304 rxShape->setPosition( Point( aShapeRect.X, aShapeRect.Y ) ); 305 rxShape->setSize( Size( aShapeRect.Width, aShapeRect.Height ) ); 306 convertShapeProperties( rxShape ); 307 } 308 } 309 } 310 311 // protected ------------------------------------------------------------------ 312 313 Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor ) const 314 { 315 /* Calculate shape rectangle. Applications may do something special 316 according to some imported shape client data (e.g. Excel cell anchor). */ 317 Rectangle aShapeRect; 318 const ClientData* pClientData = getClientData(); 319 if( !pClientData || !mrDrawing.convertClientAnchor( aShapeRect, pClientData->maAnchor ) ) 320 aShapeRect = getRectangle( pParentAnchor ); 321 return aShapeRect; 322 } 323 324 void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const 325 { 326 ::oox::drawingml::ShapePropertyMap aPropMap( mrDrawing.getFilter().getModelObjectHelper() ); 327 const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper(); 328 maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rGraphicHelper ); 329 maTypeModel.maFillModel.pushToPropMap( aPropMap, rGraphicHelper ); 330 PropertySet( rxShape ).setProperties( aPropMap ); 331 } 332 333 // ============================================================================ 334 335 SimpleShape::SimpleShape( Drawing& rDrawing, const OUString& rService ) : 336 ShapeBase( rDrawing ), 337 maService( rService ) 338 { 339 } 340 341 Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const 342 { 343 Reference< XShape > xShape = mrDrawing.createAndInsertXShape( maService, rxShapes, rShapeRect ); 344 convertShapeProperties( xShape ); 345 return xShape; 346 } 347 348 // ============================================================================ 349 350 RectangleShape::RectangleShape( Drawing& rDrawing ) : 351 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ) ) 352 { 353 } 354 355 // ============================================================================ 356 357 EllipseShape::EllipseShape( Drawing& rDrawing ) : 358 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ) ) 359 { 360 } 361 362 // ============================================================================ 363 364 PolyLineShape::PolyLineShape( Drawing& rDrawing ) : 365 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ) ) 366 { 367 } 368 369 Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const 370 { 371 Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); 372 // polygon path 373 Rectangle aCoordSys = getCoordSystem(); 374 if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) ) 375 { 376 ::std::vector< Point > aAbsPoints; 377 for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt ) 378 aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) ); 379 PointSequenceSequence aPointSeq( 1 ); 380 aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints ); 381 PropertySet aPropSet( xShape ); 382 aPropSet.setProperty( PROP_PolyPolygon, aPointSeq ); 383 } 384 return xShape; 385 } 386 387 // ============================================================================ 388 389 CustomShape::CustomShape( Drawing& rDrawing ) : 390 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) ) 391 { 392 } 393 394 Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const 395 { 396 // try to create a custom shape 397 Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect ); 398 if( xShape.is() ) try 399 { 400 // create the custom shape geometry 401 Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW ); 402 xDefaulter->createCustomShapeDefaults( OUString::valueOf( getShapeType() ) ); 403 // convert common properties 404 convertShapeProperties( xShape ); 405 } 406 catch( Exception& ) 407 { 408 } 409 return xShape; 410 } 411 412 // ============================================================================ 413 414 ComplexShape::ComplexShape( Drawing& rDrawing ) : 415 CustomShape( rDrawing ) 416 { 417 } 418 419 Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const 420 { 421 XmlFilterBase& rFilter = mrDrawing.getFilter(); 422 sal_Int32 nShapeType = getShapeType(); 423 OUString aGraphicPath = getGraphicPath(); 424 425 // try to find registered OLE object info 426 if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) ) 427 { 428 OSL_ENSURE( nShapeType == VML_SHAPETYPE_PICTUREFRAME, "ComplexShape::implConvertAndInsert - unexpected shape type" ); 429 430 // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here 431 if( pOleObjectInfo->mbDmlShape ) 432 return Reference< XShape >(); 433 434 PropertyMap aOleProps; 435 Size aOleSize( rShapeRect.Width, rShapeRect.Height ); 436 if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) ) 437 { 438 Reference< XShape > xShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ), rxShapes, rShapeRect ); 439 if( xShape.is() ) 440 { 441 // set the replacement graphic 442 if( aGraphicPath.getLength() > 0 ) 443 { 444 Reference< XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath ); 445 if( xGraphic.is() ) 446 aOleProps[ PROP_Graphic ] <<= xGraphic; 447 } 448 449 PropertySet aPropSet( xShape ); 450 aPropSet.setProperties( aOleProps ); 451 452 return xShape; 453 } 454 } 455 } 456 457 // try to find registered form control info 458 const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId ); 459 if( pControlInfo && (pControlInfo->maFragmentPath.getLength() > 0) ) 460 { 461 OSL_ENSURE( nShapeType == VML_SHAPETYPE_HOSTCONTROL, "ComplexShape::implConvertAndInsert - unexpected shape type" ); 462 OUString aShapeName = getShapeName(); 463 if( aShapeName.getLength() > 0 ) 464 { 465 OSL_ENSURE( aShapeName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" ); 466 // load the control properties from fragment 467 ::oox::ole::EmbeddedControl aControl( aShapeName ); 468 if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) ) 469 { 470 // create and return the control shape (including control model) 471 sal_Int32 nCtrlIndex = -1; 472 Reference< XShape > xShape = mrDrawing.createAndInsertXControlShape( aControl, rxShapes, rShapeRect, nCtrlIndex ); 473 // on error, proceed and try to create picture from replacement image 474 if( xShape.is() ) 475 return xShape; 476 } 477 } 478 } 479 480 // host application wants to create the shape (do not try failed OLE controls again) 481 if( (nShapeType == VML_SHAPETYPE_HOSTCONTROL) && !pControlInfo ) 482 { 483 OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" ); 484 Reference< XShape > xShape = mrDrawing.createAndInsertClientXShape( *this, rxShapes, rShapeRect ); 485 if( xShape.is() ) 486 return xShape; 487 } 488 489 // try to create a picture object 490 if( aGraphicPath.getLength() > 0 ) 491 { 492 Reference< XShape > xShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ), rxShapes, rShapeRect ); 493 if( xShape.is() ) 494 { 495 OUString aGraphicUrl = rFilter.getGraphicHelper().importEmbeddedGraphicObject( aGraphicPath ); 496 if( aGraphicUrl.getLength() > 0 ) 497 { 498 PropertySet aPropSet( xShape ); 499 aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl ); 500 } 501 } 502 return xShape; 503 } 504 505 // default: try to create a custom shape 506 return CustomShape::implConvertAndInsert( rxShapes, rShapeRect ); 507 } 508 509 // ============================================================================ 510 511 GroupShape::GroupShape( Drawing& rDrawing ) : 512 ShapeBase( rDrawing ), 513 mxChildren( new ShapeContainer( rDrawing ) ) 514 { 515 } 516 517 GroupShape::~GroupShape() 518 { 519 } 520 521 void GroupShape::finalizeFragmentImport() 522 { 523 // basic shape processing 524 ShapeBase::finalizeFragmentImport(); 525 // finalize all child shapes 526 mxChildren->finalizeFragmentImport(); 527 } 528 529 const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const 530 { 531 return mxChildren->getShapeTypeById( rShapeId, true ); 532 } 533 534 const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const 535 { 536 return mxChildren->getShapeById( rShapeId, true ); 537 } 538 539 Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const 540 { 541 Reference< XShape > xGroupShape; 542 // check that this shape contains children and a valid coordinate system 543 ShapeParentAnchor aParentAnchor; 544 aParentAnchor.maShapeRect = rShapeRect; 545 aParentAnchor.maCoordSys = getCoordSystem(); 546 if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try 547 { 548 xGroupShape = mrDrawing.createAndInsertXShape( CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rxShapes, rShapeRect ); 549 Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW ); 550 mxChildren->convertAndInsert( xChildShapes, &aParentAnchor ); 551 // no child shape has been created - delete the group shape 552 if( !xChildShapes->hasElements() ) 553 { 554 rxShapes->remove( xGroupShape ); 555 xGroupShape.clear(); 556 } 557 } 558 catch( Exception& ) 559 { 560 } 561 return xGroupShape; 562 } 563 564 // ============================================================================ 565 566 } // namespace vml 567 } // namespace oox 568