merge the formfield patch from ooo-build
[ooovba.git] / oox / source / vml / vmlshape.cxx
blobfe07172599a9aa1d0ede44b721970e6b6d3e9d76
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: vmlshape.cxx,v $
10 * $Revision: 1.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/vml/vmlshape.hxx"
32 #include <rtl/math.hxx>
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/beans/PropertyValues.hpp>
35 #include <com/sun/star/awt/XControlModel.hpp>
36 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
37 #include <com/sun/star/drawing/XControlShape.hpp>
38 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
39 #include <com/sun/star/drawing/XShapes.hpp>
40 #include <com/sun/star/graphic/XGraphic.hpp>
41 #include "properties.hxx"
42 #include "oox/helper/propertymap.hxx"
43 #include "oox/helper/propertyset.hxx"
44 #include "oox/core/xmlfilterbase.hxx"
45 #include "oox/ole/axcontrol.hxx"
46 #include "oox/ole/axcontrolfragment.hxx"
47 #include "oox/ole/oleobjecthelper.hxx"
48 #include "oox/vml/vmldrawing.hxx"
49 #include "oox/vml/vmlshapecontainer.hxx"
51 using ::rtl::OUString;
52 using ::com::sun::star::uno::Exception;
53 using ::com::sun::star::uno::Reference;
54 using ::com::sun::star::uno::UNO_QUERY;
55 using ::com::sun::star::uno::UNO_QUERY_THROW;
56 using ::com::sun::star::uno::UNO_SET_THROW;
57 using ::com::sun::star::lang::XMultiServiceFactory;
58 using ::com::sun::star::awt::Point;
59 using ::com::sun::star::awt::Rectangle;
60 using ::com::sun::star::awt::Size;
61 using ::com::sun::star::awt::XControlModel;
62 using ::com::sun::star::graphic::XGraphic;
63 using ::com::sun::star::drawing::PointSequenceSequence;
64 using ::com::sun::star::drawing::XControlShape;
65 using ::com::sun::star::drawing::XEnhancedCustomShapeDefaulter;
66 using ::com::sun::star::drawing::XShape;
67 using ::com::sun::star::drawing::XShapes;
68 using ::oox::core::XmlFilterBase;
70 namespace oox {
71 namespace vml {
73 // ============================================================================
75 namespace {
77 Point lclGetAbsPoint( const Point& rRelPoint, const Rectangle& rShapeRect, const Rectangle& rCoordSys )
79 double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
80 double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
81 Point aAbsPoint;
82 aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 );
83 aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 );
84 return aAbsPoint;
87 Rectangle lclGetAbsRect( const Rectangle& rRelRect, const Rectangle& rShapeRect, const Rectangle& rCoordSys )
89 double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
90 double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
91 Rectangle aAbsRect;
92 aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 );
93 aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 );
94 aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 );
95 aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 );
96 return aAbsRect;
99 Reference< XShape > lclCreateXShape( const XmlFilterBase& rFilter, const OUString& rService )
101 OSL_ENSURE( rService.getLength() > 0, "lclCreateXShape - missing UNO shape service name" );
102 Reference< XShape > xShape;
105 Reference< XMultiServiceFactory > xFactory( rFilter.getModel(), UNO_QUERY_THROW );
106 xShape.set( xFactory->createInstance( rService ), UNO_QUERY_THROW );
108 catch( Exception& )
111 OSL_ENSURE( xShape.is(), "lclCreateXShape - cannot instanciate shape object" );
112 return xShape;
115 void lclInsertXShape( const Reference< XShapes >& rxShapes, const Reference< XShape >& rxShape )
117 OSL_ENSURE( rxShapes.is(), "lclInsertXShape - missing XShapes container" );
118 OSL_ENSURE( rxShape.is(), "lclInsertXShape - missing XShape" );
119 if( rxShapes.is() && rxShape.is() ) try
121 // insert shape into passed shape collection (maybe drawpage or group shape)
122 rxShapes->add( rxShape );
124 catch( Exception& )
129 void lclSetXShapeRect( const Reference< XShape >& rxShape, const Rectangle& rShapeRect )
131 OSL_ENSURE( rxShape.is(), "lclSetXShapeRect - missing XShape" );
132 if( rxShape.is() )
134 rxShape->setPosition( Point( rShapeRect.X, rShapeRect.Y ) );
135 rxShape->setSize( Size( rShapeRect.Width, rShapeRect.Height ) );
139 Reference< XShape > lclCreateAndInsertXShape( const XmlFilterBase& rFilter,
140 const Reference< XShapes >& rxShapes, const OUString& rService, const Rectangle& rShapeRect )
142 Reference< XShape > xShape = lclCreateXShape( rFilter, rService );
143 lclInsertXShape( rxShapes, xShape );
144 lclSetXShapeRect( xShape, rShapeRect );
145 return xShape;
148 } // namespace
150 // ============================================================================
152 ShapeTypeModel::ShapeTypeModel()
156 void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource )
158 moShapeType.assignIfUsed( rSource.moShapeType );
159 moCoordPos.assignIfUsed( rSource.moCoordPos );
160 moCoordSize.assignIfUsed( rSource.moCoordSize );
161 /* The style properties position, left, top, width, height, margin-left,
162 margin-top are not derived from shape template to shape. */
163 maStrokeModel.assignUsed( rSource.maStrokeModel );
164 maFillModel.assignUsed( rSource.maFillModel );
165 moGraphicPath.assignIfUsed( rSource.moGraphicPath );
166 moGraphicTitle.assignIfUsed( rSource.moGraphicTitle );
169 // ----------------------------------------------------------------------------
171 ShapeType::ShapeType( const Drawing& rDrawing ) :
172 mrDrawing( rDrawing )
176 ShapeType::~ShapeType()
180 OUString ShapeType::getGraphicPath() const
182 return maTypeModel.moGraphicPath.get( OUString() );
185 Rectangle ShapeType::getCoordSystem() const
187 Int32Pair aCoordPos = maTypeModel.moCoordPos.get( Int32Pair( 0, 0 ) );
188 Int32Pair aCoordSize = maTypeModel.moCoordSize.get( Int32Pair( 1000, 1000 ) );
189 return Rectangle( aCoordPos.first, aCoordPos.second, aCoordSize.first, aCoordSize.second );
192 Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const
194 return pParentAnchor ?
195 lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) :
196 getAbsRectangle();
199 Rectangle ShapeType::getAbsRectangle() const
201 const XmlFilterBase& rFilter = mrDrawing.getFilter();
202 return Rectangle(
203 ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maLeft, 0, true, true ) + ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maMarginLeft, 0, true, true ),
204 ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maMarginTop, 0, false, true ),
205 ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maWidth, 0, true, true ),
206 ConversionHelper::decodeMeasureToHmm( rFilter, maTypeModel.maHeight, 0, false, true ) );
209 Rectangle ShapeType::getRelRectangle() const
211 return Rectangle(
212 maTypeModel.maLeft.toInt32(),
213 maTypeModel.maTop.toInt32(),
214 maTypeModel.maWidth.toInt32(),
215 maTypeModel.maHeight.toInt32() );
218 // ============================================================================
220 ShapeClientData::ShapeClientData() :
221 mnObjType( XML_TOKEN_INVALID ),
222 mnCol( -1 ),
223 mnRow( -1 ),
224 mbPrintObject( true ),
225 mbVisible( false )
229 // ----------------------------------------------------------------------------
231 ShapeModel::ShapeModel()
235 ShapeClientData& ShapeModel::createClientData()
237 mxClientData.reset( new ShapeClientData );
238 return *mxClientData;
241 // ----------------------------------------------------------------------------
243 ShapeBase::ShapeBase( const Drawing& rDrawing ) :
244 ShapeType( rDrawing )
248 void ShapeBase::finalizeFragmentImport()
250 // resolve shape template reference
251 if( (maShapeModel.maType.getLength() > 1) && (maShapeModel.maType[ 0 ] == '#') )
252 if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( maShapeModel.maType.copy( 1 ), true ) )
253 maTypeModel.assignUsed( pShapeType->getTypeModel() );
256 const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
258 return 0;
261 const ShapeBase* ShapeBase::getChildById( const OUString& ) const
263 return 0;
266 Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const
268 Reference< XShape > xShape;
269 if( mrDrawing.isShapeSupported( *this ) )
271 /* Calculate shape rectangle. Applications may do something special
272 according to some imported shape client data (e.g. Excel cell anchor). */
273 Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
274 // convert the shape, if the calculated rectangle is not empty
275 if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() )
276 xShape = implConvertAndInsert( rxShapes, aShapeRect );
278 return xShape;
281 void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const
283 if( rxShape.is() )
285 /* Calculate shape rectangle. Applications may do something special
286 according to some imported shape client data (e.g. Excel cell anchor). */
287 Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
288 // convert the shape, if the calculated rectangle is not empty
289 if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) )
291 lclSetXShapeRect( rxShape, aShapeRect );
292 convertShapeProperties( rxShape );
297 // protected ------------------------------------------------------------------
299 Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor ) const
301 /* Calculate shape rectangle. Applications may do something special
302 according to some imported shape client data (e.g. Excel cell anchor). */
303 Rectangle aShapeRect;
304 if( !maShapeModel.mxClientData.get() || !mrDrawing.convertShapeClientAnchor( aShapeRect, maShapeModel.mxClientData->maAnchor ) )
305 aShapeRect = getRectangle( pParentAnchor );
306 return aShapeRect;
309 void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const
311 PropertyMap aPropMap;
313 maTypeModel.maStrokeModel.pushToPropMap( aPropMap, mrDrawing.getFilter() );
314 maTypeModel.maFillModel.pushToPropMap( aPropMap, mrDrawing.getFilter() );
316 PropertySet aPropSet( rxShape );
317 aPropSet.setProperties( aPropMap );
320 // ============================================================================
322 SimpleShape::SimpleShape( const Drawing& rDrawing, const OUString& rService ) :
323 ShapeBase( rDrawing ),
324 maService( rService )
328 Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
330 Reference< XShape > xShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, maService, rShapeRect );
331 convertShapeProperties( xShape );
332 return xShape;
335 // ============================================================================
337 RectangleShape::RectangleShape( const Drawing& rDrawing ) :
338 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.RectangleShape" ) )
342 // ============================================================================
344 EllipseShape::EllipseShape( const Drawing& rDrawing ) :
345 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.EllipseShape" ) )
349 // ============================================================================
351 PolyLineShape::PolyLineShape( const Drawing& rDrawing ) :
352 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.PolyLineShape" ) )
356 Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
358 Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
359 // polygon path
360 Rectangle aCoordSys = getCoordSystem();
361 if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
363 ::std::vector< Point > aAbsPoints;
364 for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt )
365 aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) );
366 PointSequenceSequence aPointSeq( 1 );
367 aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints );
368 PropertySet aPropSet( xShape );
369 aPropSet.setProperty( PROP_PolyPolygon, aPointSeq );
371 return xShape;
374 // ============================================================================
376 CustomShape::CustomShape( const Drawing& rDrawing ) :
377 SimpleShape( rDrawing, CREATE_OUSTRING( "com.sun.star.drawing.CustomShape" ) )
381 Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
383 // try to create a custom shape
384 Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
385 if( xShape.is() ) try
387 // create the custom shape geometry
388 Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW );
389 xDefaulter->createCustomShapeDefaults( OUString::valueOf( maTypeModel.moShapeType.get( 0 ) ) );
390 // convert common properties
391 convertShapeProperties( xShape );
393 catch( Exception& )
396 return xShape;
399 // ============================================================================
401 ComplexShape::ComplexShape( const Drawing& rDrawing ) :
402 CustomShape( rDrawing )
406 Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
408 XmlFilterBase& rFilter = mrDrawing.getFilter();
409 OUString aGraphicPath = getGraphicPath();
411 // try to find registered OLE object info
412 if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) )
414 // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
415 if( pOleObjectInfo->mbDmlShape )
416 return Reference< XShape >();
418 PropertyMap aOleProps;
419 Size aOleSize( rShapeRect.Width, rShapeRect.Height );
420 if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) )
422 Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.OLE2Shape" ), rShapeRect );
423 if( xShape.is() )
425 // set the replacement graphic
426 if( aGraphicPath.getLength() > 0 )
428 Reference< XGraphic > xGraphic = rFilter.importEmbeddedGraphic( aGraphicPath );
429 if( xGraphic.is() )
430 aOleProps[ PROP_Graphic ] <<= xGraphic;
433 PropertySet aPropSet( xShape );
434 aPropSet.setProperties( aOleProps );
436 return xShape;
441 // try to find registered form control info
442 const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId );
443 if( pControlInfo && (pControlInfo->maFragmentPath.getLength() > 0) && (maTypeModel.maName.getLength() > 0) )
445 OSL_ENSURE( maTypeModel.maName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" );
446 ::oox::ole::AxControl aControl( maTypeModel.maName );
447 // load the control properties from fragment
448 if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) ) try
450 // create control model and insert it into the form of the draw page
451 Reference< XControlModel > xCtrlModel( aControl.convertAndInsert( mrDrawing.getControlHelper() ), UNO_SET_THROW );
452 if( maShapeModel.mxClientData.get() )
453 mrDrawing.convertControlClientData( xCtrlModel, *maShapeModel.mxClientData );
455 // create the control shape, set control model at the shape
456 Reference< XShape > xShape = lclCreateAndInsertXShape(
457 rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.ControlShape" ), rShapeRect );
458 Reference< XControlShape > xCtrlShape( xShape, UNO_QUERY ); // do not throw, but always return the shape
459 if( xCtrlShape.is() )
460 xCtrlShape->setControl( xCtrlModel );
461 return xShape;
463 catch( Exception& )
466 // on error, proceed and try to create picture from replacement image
469 // try to create a picture object
470 if( aGraphicPath.getLength() > 0 )
472 Reference< XShape > xShape = lclCreateAndInsertXShape( rFilter, rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GraphicObjectShape" ), rShapeRect );
473 if( xShape.is() )
475 OUString aGraphicUrl = rFilter.importEmbeddedGraphicObject( aGraphicPath );
476 if( aGraphicUrl.getLength() > 0 )
478 PropertySet aPropSet( xShape );
479 aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl );
482 return xShape;
485 // default: try to create a custom shape
486 return CustomShape::implConvertAndInsert( rxShapes, rShapeRect );
489 // ============================================================================
491 GroupShape::GroupShape( const Drawing& rDrawing ) :
492 ShapeBase( rDrawing ),
493 mxChildren( new ShapeContainer( rDrawing ) )
497 GroupShape::~GroupShape()
501 void GroupShape::finalizeFragmentImport()
503 // basic shape processing
504 ShapeBase::finalizeFragmentImport();
505 // finalize all child shapes
506 mxChildren->finalizeFragmentImport();
509 const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const
511 return mxChildren->getShapeTypeById( rShapeId, true );
514 const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const
516 return mxChildren->getShapeById( rShapeId, true );
519 Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const Rectangle& rShapeRect ) const
521 Reference< XShape > xGroupShape;
522 // check that this shape contains children and a valid coordinate system
523 ShapeParentAnchor aParentAnchor;
524 aParentAnchor.maShapeRect = rShapeRect;
525 aParentAnchor.maCoordSys = getCoordSystem();
526 if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try
528 xGroupShape = lclCreateAndInsertXShape( mrDrawing.getFilter(), rxShapes, CREATE_OUSTRING( "com.sun.star.drawing.GroupShape" ), rShapeRect );
529 Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
530 mxChildren->convertAndInsert( xChildShapes, &aParentAnchor );
531 // no child shape has been created - delete the group shape
532 if( !xChildShapes->hasElements() )
534 rxShapes->remove( xGroupShape );
535 xGroupShape.clear();
538 catch( Exception& )
541 return xGroupShape;
544 // ============================================================================
546 } // namespace vml
547 } // namespace oox