xref: /aoo41x/main/oox/source/vml/vmlshape.cxx (revision cdf0e10c)
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