1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <boost/optional.hpp>
23 #include "oox/vml/vmlshape.hxx"
25 #include <com/sun/star/beans/PropertyValues.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/awt/XControlModel.hpp>
28 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
29 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
31 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
32 #include <com/sun/star/drawing/XShapes.hpp>
33 #include <com/sun/star/drawing/XControlShape.hpp>
34 #include <com/sun/star/graphic/XGraphic.hpp>
35 #include <com/sun/star/table/BorderLine2.hpp>
36 #include <com/sun/star/text/HoriOrientation.hpp>
37 #include <com/sun/star/text/RelOrientation.hpp>
38 #include <com/sun/star/text/SizeType.hpp>
39 #include <com/sun/star/text/VertOrientation.hpp>
40 #include <com/sun/star/text/WrapTextMode.hpp>
41 #include <com/sun/star/text/XTextContent.hpp>
42 #include <com/sun/star/text/XTextDocument.hpp>
43 #include <com/sun/star/text/XTextFrame.hpp>
44 #include <com/sun/star/text/TextContentAnchorType.hpp>
45 #include <rtl/math.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <svx/svdtrans.hxx>
48 #include "oox/drawingml/shapepropertymap.hxx"
49 #include "oox/helper/graphichelper.hxx"
50 #include "oox/helper/propertyset.hxx"
51 #include "oox/ole/axcontrol.hxx"
52 #include "oox/ole/axcontrolfragment.hxx"
53 #include "oox/ole/oleobjecthelper.hxx"
54 #include "oox/vml/vmldrawing.hxx"
55 #include "oox/vml/vmlshapecontainer.hxx"
56 #include "oox/vml/vmltextbox.hxx"
57 #include "oox/core/xmlfilterbase.hxx"
58 #include "oox/helper/containerhelper.hxx"
60 using ::com::sun::star::beans::XPropertySet
;
61 using ::com::sun::star::uno::Any
;
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::text
;
69 // ============================================================================
71 using namespace ::com::sun::star
;
72 using namespace ::com::sun::star::drawing
;
73 using namespace ::com::sun::star::graphic
;
74 using namespace ::com::sun::star::uno
;
75 using namespace ::com::sun::star::io
;
77 using ::oox::core::XmlFilterBase
;
79 // ============================================================================
83 const sal_Int32 VML_SHAPETYPE_PICTUREFRAME
= 75;
84 const sal_Int32 VML_SHAPETYPE_HOSTCONTROL
= 201;
86 // ----------------------------------------------------------------------------
88 awt::Point
lclGetAbsPoint( const awt::Point
& rRelPoint
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
90 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
91 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
93 aAbsPoint
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelPoint
.X
- rCoordSys
.X
) + 0.5 );
94 aAbsPoint
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelPoint
.Y
- rCoordSys
.Y
) + 0.5 );
98 awt::Rectangle
lclGetAbsRect( const awt::Rectangle
& rRelRect
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
100 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
101 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
102 awt::Rectangle aAbsRect
;
103 aAbsRect
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelRect
.X
- rCoordSys
.X
) + 0.5 );
104 aAbsRect
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelRect
.Y
- rCoordSys
.Y
) + 0.5 );
105 aAbsRect
.Width
= static_cast< sal_Int32
>( fWidthRatio
* rRelRect
.Width
+ 0.5 );
106 aAbsRect
.Height
= static_cast< sal_Int32
>( fHeightRatio
* rRelRect
.Height
+ 0.5 );
112 // ============================================================================
114 ShapeTypeModel::ShapeTypeModel():
115 mbAutoHeight( sal_False
),
116 mbVisible( sal_True
)
120 void ShapeTypeModel::assignUsed( const ShapeTypeModel
& rSource
)
122 moShapeType
.assignIfUsed( rSource
.moShapeType
);
123 moCoordPos
.assignIfUsed( rSource
.moCoordPos
);
124 moCoordSize
.assignIfUsed( rSource
.moCoordSize
);
125 /* The style properties position, left, top, width, height, margin-left,
126 margin-top are not derived from shape template to shape. */
127 maStrokeModel
.assignUsed( rSource
.maStrokeModel
);
128 maFillModel
.assignUsed( rSource
.maFillModel
);
129 moGraphicPath
.assignIfUsed( rSource
.moGraphicPath
);
130 moGraphicTitle
.assignIfUsed( rSource
.moGraphicTitle
);
133 // ----------------------------------------------------------------------------
135 ShapeType::ShapeType( Drawing
& rDrawing
) :
136 mrDrawing( rDrawing
)
140 ShapeType::~ShapeType()
144 sal_Int32
ShapeType::getShapeType() const
146 return maTypeModel
.moShapeType
.get( 0 );
149 OUString
ShapeType::getGraphicPath() const
151 return maTypeModel
.moGraphicPath
.get( OUString() );
154 awt::Rectangle
ShapeType::getCoordSystem() const
156 Int32Pair aCoordPos
= maTypeModel
.moCoordPos
.get( Int32Pair( 0, 0 ) );
157 Int32Pair aCoordSize
= maTypeModel
.moCoordSize
.get( Int32Pair( 1000, 1000 ) );
158 return awt::Rectangle( aCoordPos
.first
, aCoordPos
.second
, aCoordSize
.first
, aCoordSize
.second
);
161 awt::Rectangle
ShapeType::getRectangle( const ShapeParentAnchor
* pParentAnchor
) const
163 return pParentAnchor
?
164 lclGetAbsRect( getRelRectangle(), pParentAnchor
->maShapeRect
, pParentAnchor
->maCoordSys
) :
168 awt::Rectangle
ShapeType::getAbsRectangle() const
170 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
172 sal_Int32 nWidth
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maWidth
, 0, true, true );
176 sal_Int32 nHeight
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maHeight
, 0, false, true );
180 sal_Int32 nLeft
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maLeft
, 0, true, true )
181 + ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maMarginLeft
, 0, true, true );
182 if (nLeft
== 0 && maTypeModel
.maPosition
== "absolute")
185 return awt::Rectangle(
187 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maTop
, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maMarginTop
, 0, false, true ),
191 awt::Rectangle
ShapeType::getRelRectangle() const
193 sal_Int32 nWidth
= maTypeModel
.maWidth
.toInt32();
197 sal_Int32 nHeight
= maTypeModel
.maHeight
.toInt32();
201 return awt::Rectangle(
202 maTypeModel
.maLeft
.toInt32(),
203 maTypeModel
.maTop
.toInt32(),
207 // ============================================================================
209 ClientData::ClientData() :
210 mnObjType( XML_TOKEN_INVALID
),
211 mnTextHAlign( XML_Left
),
212 mnTextVAlign( XML_Top
),
215 mnChecked( VML_CLIENTDATA_UNCHECKED
),
216 mnDropStyle( XML_Combo
),
223 mnSelType( XML_Single
),
224 mnVTEdit( VML_CLIENTDATA_TEXT
),
225 mbPrintObject( true ),
230 mbMultiLine( false ),
232 mbSecretEdit( false )
236 // ----------------------------------------------------------------------------
238 ShapeModel::ShapeModel()
242 ShapeModel::~ShapeModel()
246 TextBox
& ShapeModel::createTextBox(ShapeTypeModel
& rModel
)
248 mxTextBox
.reset( new TextBox(rModel
) );
252 ClientData
& ShapeModel::createClientData()
254 mxClientData
.reset( new ClientData
);
255 return *mxClientData
;
258 // ----------------------------------------------------------------------------
260 ShapeBase::ShapeBase( Drawing
& rDrawing
) :
261 ShapeType( rDrawing
)
265 void ShapeBase::finalizeFragmentImport()
267 // resolve shape template reference
268 if( (maShapeModel
.maType
.getLength() > 1) && (maShapeModel
.maType
[ 0 ] == '#') )
269 if( const ShapeType
* pShapeType
= mrDrawing
.getShapes().getShapeTypeById( maShapeModel
.maType
.copy( 1 ), true ) )
270 maTypeModel
.assignUsed( pShapeType
->getTypeModel() );
273 OUString
ShapeBase::getShapeName() const
275 if( !maTypeModel
.maShapeName
.isEmpty() )
276 return maTypeModel
.maShapeName
;
278 OUString aBaseName
= mrDrawing
.getShapeBaseName( *this );
279 if( !aBaseName
.isEmpty() )
281 sal_Int32 nShapeIdx
= mrDrawing
.getLocalShapeIndex( getShapeId() );
283 return OUStringBuffer( aBaseName
).append( sal_Unicode( ' ' ) ).append( nShapeIdx
).makeStringAndClear();
289 const ShapeType
* ShapeBase::getChildTypeById( const OUString
& ) const
294 const ShapeBase
* ShapeBase::getChildById( const OUString
& ) const
299 Reference
< XShape
> ShapeBase::convertAndInsert( const Reference
< XShapes
>& rxShapes
, const ShapeParentAnchor
* pParentAnchor
) const
301 Reference
< XShape
> xShape
;
302 if( mrDrawing
.isShapeSupported( *this ) )
304 /* Calculate shape rectangle. Applications may do something special
305 according to some imported shape client data (e.g. Excel cell anchor). */
306 awt::Rectangle aShapeRect
= calcShapeRectangle( pParentAnchor
);
308 if( ((aShapeRect
.Width
> 0) || (aShapeRect
.Height
> 0)) && rxShapes
.is() )
310 xShape
= implConvertAndInsert( rxShapes
, aShapeRect
);
313 // set imported or generated shape name (not supported by form controls)
314 PropertySet
aShapeProp( xShape
);
315 if( aShapeProp
.hasProperty( PROP_Name
) )
316 aShapeProp
.setProperty( PROP_Name
, getShapeName() );
317 Reference
< XControlShape
> xControlShape( xShape
, uno::UNO_QUERY
);
318 if ( xControlShape
.is() && !getTypeModel().mbVisible
)
320 PropertySet
aControlShapeProp( xControlShape
->getControl() );
321 aControlShapeProp
.setProperty( PROP_EnableVisible
, uno::makeAny( sal_False
) );
323 /* Notify the drawing that a new shape has been inserted. For
324 convenience, pass the rectangle that contains position and
325 size of the shape. */
326 bool bGroupChild
= pParentAnchor
!= 0;
327 mrDrawing
.notifyXShapeInserted( xShape
, aShapeRect
, *this, bGroupChild
);
331 SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
336 void ShapeBase::convertFormatting( const Reference
< XShape
>& rxShape
, const ShapeParentAnchor
* pParentAnchor
) const
340 /* Calculate shape rectangle. Applications may do something special
341 according to some imported shape client data (e.g. Excel cell anchor). */
342 awt::Rectangle aShapeRect
= calcShapeRectangle( pParentAnchor
);
344 // convert the shape, if the calculated rectangle is not empty
345 if( (aShapeRect
.Width
> 0) || (aShapeRect
.Height
> 0) )
347 rxShape
->setPosition( awt::Point( aShapeRect
.X
, aShapeRect
.Y
) );
348 rxShape
->setSize( awt::Size( aShapeRect
.Width
, aShapeRect
.Height
) );
349 convertShapeProperties( rxShape
);
354 // protected ------------------------------------------------------------------
356 awt::Rectangle
ShapeBase::calcShapeRectangle( const ShapeParentAnchor
* pParentAnchor
) const
358 /* Calculate shape rectangle. Applications may do something special
359 according to some imported shape client data (e.g. Excel cell anchor). */
360 awt::Rectangle aShapeRect
;
361 const ClientData
* pClientData
= getClientData();
362 if( !pClientData
|| !mrDrawing
.convertClientAnchor( aShapeRect
, pClientData
->maAnchor
) )
363 aShapeRect
= getRectangle( pParentAnchor
);
367 void ShapeBase::convertShapeProperties( const Reference
< XShape
>& rxShape
) const
369 ::oox::drawingml::ShapePropertyMap
aPropMap( mrDrawing
.getFilter().getModelObjectHelper() );
370 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
371 maTypeModel
.maStrokeModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
372 maTypeModel
.maFillModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
374 uno::Reference
<lang::XServiceInfo
> xSInfo(rxShape
, uno::UNO_QUERY_THROW
);
375 if (xSInfo
->supportsService("com.sun.star.text.TextFrame"))
377 // Any other service supporting the ShadowFormat property?
378 maTypeModel
.maShadowModel
.pushToPropMap(aPropMap
, rGraphicHelper
);
379 // TextFrames have BackColor, not FillColor
380 if (aPropMap
.hasProperty(PROP_FillColor
))
382 aPropMap
.setProperty(PROP_BackColor
, aPropMap
[PROP_FillColor
]);
383 aPropMap
.erase(PROP_FillColor
);
385 // And no LineColor property; individual borders can have colors and widths
386 boost::optional
<sal_Int32
> oLineWidth
;
387 if (maTypeModel
.maStrokeModel
.moWeight
.has())
388 oLineWidth
.reset(ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maStrokeModel
.moWeight
.get(), 0, false, false));
389 if (aPropMap
.hasProperty(PROP_LineColor
))
391 uno::Reference
<beans::XPropertySet
> xPropertySet(rxShape
, uno::UNO_QUERY
);
392 static sal_Int32 aBorders
[] = {
393 PROP_TopBorder
, PROP_LeftBorder
, PROP_BottomBorder
, PROP_RightBorder
395 for (unsigned int i
= 0; i
< SAL_N_ELEMENTS(aBorders
); ++i
)
397 table::BorderLine2 aBorderLine
= xPropertySet
->getPropertyValue(PropertyMap::getPropertyName(aBorders
[i
])).get
<table::BorderLine2
>();
398 aBorderLine
.Color
= aPropMap
[PROP_LineColor
].get
<sal_Int32
>();
400 aBorderLine
.LineWidth
= *oLineWidth
;
401 aPropMap
.setProperty(aBorders
[i
], uno::makeAny(aBorderLine
));
403 aPropMap
.erase(PROP_LineColor
);
406 else if (xSInfo
->supportsService("com.sun.star.drawing.CustomShape"))
407 maTypeModel
.maTextpathModel
.pushToPropMap(aPropMap
, rxShape
);
409 PropertySet( rxShape
).setProperties( aPropMap
);
412 // ============================================================================
414 SimpleShape::SimpleShape( Drawing
& rDrawing
, const OUString
& rService
) :
415 ShapeBase( rDrawing
),
416 maService( rService
)
420 void lcl_setSurround(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
)
422 sal_Int32 nSurround
= com::sun::star::text::WrapTextMode_THROUGHT
;
423 if ( rTypeModel
.moWrapType
.get() == "square" || rTypeModel
.moWrapType
.get()== "tight" ||
424 rTypeModel
.moWrapType
.get() == "through" )
426 nSurround
= com::sun::star::text::WrapTextMode_PARALLEL
;
427 if ( rTypeModel
.moWrapSide
.get() == "left" )
428 nSurround
= com::sun::star::text::WrapTextMode_LEFT
;
429 else if ( rTypeModel
.moWrapSide
.get() == "right" )
430 nSurround
= com::sun::star::text::WrapTextMode_RIGHT
;
432 else if ( rTypeModel
.moWrapType
.get() == "topAndBottom" )
433 nSurround
= com::sun::star::text::WrapTextMode_NONE
;
435 rPropSet
.setProperty(PROP_Surround
, nSurround
);
438 void lcl_SetAnchorType(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
)
440 if ( rTypeModel
.maPositionHorizontal
== "center" )
441 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::CENTER
));
443 if ( rTypeModel
.maPositionHorizontalRelative
== "page" )
444 rPropSet
.setAnyProperty(PROP_HoriOrientRelation
, makeAny(text::RelOrientation::PAGE_FRAME
));
446 if ( rTypeModel
.maPositionVertical
== "center" )
447 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::CENTER
));
449 if ( rTypeModel
.maPosition
== "absolute" )
451 // Word supports as-character (inline) and at-character only, absolute can't be inline.
452 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_CHARACTER
);
454 if ( rTypeModel
.maPositionVerticalRelative
== "page" )
456 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_FRAME
);
458 else if ( rTypeModel
.maPositionVerticalRelative
== "margin" )
460 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA
);
464 // Vertical placement relative to margin, because parent style must not modify vertical position
465 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::FRAME
);
468 else if( rTypeModel
.maPosition
== "relative" )
469 { // I'm not very sure this is correct either.
470 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_PARAGRAPH
);
472 else // static (is the default) means anchored inline
474 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AS_CHARACTER
);
476 lcl_setSurround( rPropSet
, rTypeModel
);
479 Reference
< XShape
> SimpleShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
481 awt::Rectangle
aShapeRect(rShapeRect
);
482 boost::optional
<sal_Int32
> oRotation
;
483 if (!maTypeModel
.maRotation
.isEmpty())
484 oRotation
.reset(maTypeModel
.maRotation
.toInt32());
485 if (!maTypeModel
.maFlip
.isEmpty())
487 if (maTypeModel
.maFlip
.equalsAscii("x"))
489 aShapeRect
.X
+= aShapeRect
.Width
;
490 aShapeRect
.Width
*= -1;
492 oRotation
.reset(360 - *oRotation
);
494 else if (maTypeModel
.maFlip
.equalsAscii("y"))
496 aShapeRect
.Y
+= aShapeRect
.Height
;
497 aShapeRect
.Height
*= -1;
501 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( maService
, rxShapes
, aShapeRect
);
502 convertShapeProperties( xShape
);
504 if ( maService
.equalsAscii( "com.sun.star.text.TextFrame" ) )
506 PropertySet( xShape
).setAnyProperty( PROP_FrameIsAutomaticHeight
, makeAny( maTypeModel
.mbAutoHeight
) );
507 PropertySet( xShape
).setAnyProperty( PROP_SizeType
, makeAny( maTypeModel
.mbAutoHeight
? SizeType::MIN
: SizeType::FIX
) );
508 if( getTextBox()->borderDistanceSet
)
510 PropertySet( xShape
).setAnyProperty( PROP_LeftBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceLeft
)));
511 PropertySet( xShape
).setAnyProperty( PROP_TopBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceTop
)));
512 PropertySet( xShape
).setAnyProperty( PROP_RightBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceRight
)));
513 PropertySet( xShape
).setAnyProperty( PROP_BottomBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceBottom
)));
518 // FIXME Setting the relative width/heigh only for everything but text frames as
519 // TextFrames already have relative widht/heigh feature... but currently not working
520 // in the way we need.
522 // Set the relative width / height if any
523 if ( !maTypeModel
.maWidthPercent
.isEmpty( ) )
525 // Only page-relative width is supported ATM
526 if ( maTypeModel
.maWidthRelative
.isEmpty() || maTypeModel
.maWidthRelative
== "page" )
528 sal_Int16 nWidth
= maTypeModel
.maWidthPercent
.toInt32() / 10;
529 // Only apply if nWidth != 0
531 PropertySet( xShape
).setAnyProperty(PROP_RelativeWidth
, makeAny( nWidth
) );
534 if ( !maTypeModel
.maHeightPercent
.isEmpty( ) )
536 // Only page-relative height is supported ATM
537 if ( maTypeModel
.maHeightRelative
.isEmpty() || maTypeModel
.maHeightRelative
== "page" )
539 sal_Int16 nHeight
= maTypeModel
.maHeightPercent
.toInt32() / 10;
540 // Only apply if nHeight != 0
542 PropertySet( xShape
).setAnyProperty(PROP_RelativeHeight
, makeAny( nHeight
) );
546 // drawinglayer default is center, MSO default is top.
547 drawing::TextVerticalAdjust eTextVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
548 if (maTypeModel
.maVTextAnchor
== "middle")
549 eTextVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
550 else if (maTypeModel
.maVTextAnchor
== "bottom")
551 eTextVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
552 PropertySet(xShape
).setAnyProperty(PROP_TextVerticalAdjust
, makeAny(eTextVerticalAdjust
));
556 getTextBox()->convert(xShape
);
557 if (getTextBox()->borderDistanceSet
)
559 PropertySet(xShape
).setAnyProperty(PROP_TextLeftDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceLeft
)));
560 PropertySet(xShape
).setAnyProperty(PROP_TextUpperDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceTop
)));
561 PropertySet(xShape
).setAnyProperty(PROP_TextRightDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceRight
)));
562 PropertySet(xShape
).setAnyProperty(PROP_TextLowerDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceBottom
)));
567 // Import Legacy Fragments (if any)
568 if( xShape
.is() && !maShapeModel
.maLegacyDiagramPath
.isEmpty() )
570 Reference
< XInputStream
> xInStrm( mrDrawing
.getFilter().openInputStream( maShapeModel
.maLegacyDiagramPath
), UNO_SET_THROW
);
572 PropertySet( xShape
).setProperty( PROP_LegacyFragment
, xInStrm
);
575 PropertySet
aPropertySet(xShape
);
576 if (xShape
.is() && oRotation
)
578 // See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation angles are clockwise, we have them as counter-clockwise.
579 // Additionally, VML type is 0..360, our is 0.36000.
580 aPropertySet
.setAnyProperty(PROP_RotateAngle
, makeAny(sal_Int32(NormAngle360((*oRotation
) * -100))));
581 // If rotation is used, simple setPosition() is not enough.
582 aPropertySet
.setAnyProperty(PROP_HoriOrientPosition
, makeAny( aShapeRect
.X
) );
583 aPropertySet
.setAnyProperty(PROP_VertOrientPosition
, makeAny( aShapeRect
.Y
) );
586 lcl_SetAnchorType(aPropertySet
, maTypeModel
);
591 Reference
< XShape
> SimpleShape::createPictureObject( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
, OUString
& rGraphicPath
) const
593 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.GraphicObjectShape", rxShapes
, rShapeRect
);
596 XmlFilterBase
& rFilter
= mrDrawing
.getFilter();
597 OUString aGraphicUrl
= rFilter
.getGraphicHelper().importEmbeddedGraphicObject( rGraphicPath
);
598 PropertySet
aPropSet( xShape
);
599 if( !aGraphicUrl
.isEmpty() )
601 aPropSet
.setProperty( PROP_GraphicURL
, aGraphicUrl
);
603 uno::Reference
< lang::XServiceInfo
> xServiceInfo(rxShapes
, uno::UNO_QUERY
);
604 // If the shape has an absolute position, set the properties accordingly, unless we're inside a group shape.
605 if ( maTypeModel
.maPosition
== "absolute" && !xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape"))
607 aPropSet
.setProperty(PROP_HoriOrientPosition
, rShapeRect
.X
);
608 aPropSet
.setProperty(PROP_VertOrientPosition
, rShapeRect
.Y
);
609 aPropSet
.setProperty(PROP_Opaque
, sal_False
);
612 lcl_SetAnchorType(aPropSet
, maTypeModel
);
617 // ============================================================================
619 RectangleShape::RectangleShape( Drawing
& rDrawing
) :
620 SimpleShape( rDrawing
, "com.sun.star.drawing.RectangleShape" )
624 Reference
<XShape
> RectangleShape::implConvertAndInsert(const Reference
<XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
626 OUString aGraphicPath
= getGraphicPath();
628 // try to create a picture object
629 if(!aGraphicPath
.isEmpty())
630 return SimpleShape::createPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
632 // default: try to create a rectangle shape
633 Reference
<XShape
> xShape
= SimpleShape::implConvertAndInsert(rxShapes
, rShapeRect
);
634 OUString sArcsize
= maTypeModel
.maArcsize
;
635 if ( !sArcsize
.isEmpty( ) )
637 sal_Unicode cLastChar
= sArcsize
[sArcsize
.getLength() - 1];
638 sal_Int32 nValue
= sArcsize
.copy( 0, sArcsize
.getLength() - 1 ).toInt32( );
639 // Get the smallest half-side
640 double size
= std::min( rShapeRect
.Height
, rShapeRect
.Width
) / 2.0;
641 sal_Int32 nRadius
= 0;
642 if ( cLastChar
== 'f' )
643 nRadius
= size
* nValue
/ 65536;
644 else if ( cLastChar
== '%' )
645 nRadius
= size
* nValue
/ 100;
646 PropertySet( xShape
).setAnyProperty( PROP_CornerRadius
, makeAny( nRadius
) );
651 // ============================================================================
653 EllipseShape::EllipseShape( Drawing
& rDrawing
) :
654 SimpleShape( rDrawing
, "com.sun.star.drawing.EllipseShape" )
658 // ============================================================================
660 PolyLineShape::PolyLineShape( Drawing
& rDrawing
) :
661 SimpleShape( rDrawing
, "com.sun.star.drawing.PolyLineShape" )
665 Reference
< XShape
> PolyLineShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
667 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
669 awt::Rectangle aCoordSys
= getCoordSystem();
670 if( !maShapeModel
.maPoints
.empty() && (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0) )
672 ::std::vector
< awt::Point
> aAbsPoints
;
673 for( ShapeModel::PointVector::const_iterator aIt
= maShapeModel
.maPoints
.begin(), aEnd
= maShapeModel
.maPoints
.end(); aIt
!= aEnd
; ++aIt
)
674 aAbsPoints
.push_back( lclGetAbsPoint( *aIt
, rShapeRect
, aCoordSys
) );
675 PointSequenceSequence
aPointSeq( 1 );
676 aPointSeq
[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints
);
677 PropertySet
aPropSet( xShape
);
678 aPropSet
.setProperty( PROP_PolyPolygon
, aPointSeq
);
683 LineShape::LineShape(Drawing
& rDrawing
)
684 : SimpleShape(rDrawing
, "com.sun.star.drawing.LineShape")
688 awt::Rectangle
LineShape::getAbsRectangle() const
690 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
691 awt::Rectangle aShapeRect
;
692 sal_Int32 nIndex
= 0;
694 aShapeRect
.X
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maFrom
.getToken(0, ',', nIndex
), 0, true, true);
695 aShapeRect
.Y
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maFrom
.getToken(0, ',', nIndex
), 0, false, true);
697 aShapeRect
.Width
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maTo
.getToken(0, ',', nIndex
), 0, true, true) - aShapeRect
.X
;
698 aShapeRect
.Height
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maTo
.getToken(0, ',', nIndex
), 0, false, true) - aShapeRect
.Y
;
702 awt::Rectangle
LineShape::getRelRectangle() const
704 awt::Rectangle aShapeRect
;
705 sal_Int32 nIndex
= 0;
707 aShapeRect
.X
= maShapeModel
.maFrom
.getToken(0, ',', nIndex
).toInt32();
708 aShapeRect
.Y
= maShapeModel
.maFrom
.getToken(0, ',', nIndex
).toInt32();
710 aShapeRect
.Width
= maShapeModel
.maTo
.getToken(0, ',', nIndex
).toInt32() - aShapeRect
.X
;
711 aShapeRect
.Height
= maShapeModel
.maTo
.getToken(0, ',', nIndex
).toInt32() - aShapeRect
.Y
;
715 // ============================================================================
717 BezierShape::BezierShape(Drawing
& rDrawing
)
718 : SimpleShape(rDrawing
, "com.sun.star.drawing.OpenBezierShape")
722 Reference
< XShape
> BezierShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
724 awt::Rectangle aCoordSys
= getCoordSystem();
725 PolyPolygonBezierCoords aBezierCoords
;
727 // If we have an 'x' in the last part of the path it means it is closed...
728 sal_Int32 nPos
= maShapeModel
.maVmlPath
.lastIndexOf(',');
729 if ( nPos
!= -1 && maShapeModel
.maVmlPath
.copy(nPos
).indexOf('x') != -1 )
731 const_cast<BezierShape
*>( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
734 if( (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0) )
736 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
738 // Bezier paths may consist of one or more sub-paths
739 typedef ::std::vector
< ::std::vector
< awt::Point
> > SubPathList
;
740 typedef ::std::vector
< ::std::vector
< PolygonFlags
> > FlagsList
;
741 SubPathList aCoordLists
;
742 FlagsList aFlagLists
;
743 sal_Int32 nIndex
= 0;
745 // Curve defined by to, from, control1 and control2 attributes
746 if ( maShapeModel
.maVmlPath
.isEmpty() )
748 aCoordLists
.push_back( ::std::vector
< awt::Point
>() );
749 aFlagLists
.push_back( ::std::vector
< PolygonFlags
>() );
752 aCoordLists
[ 0 ].push_back(
753 awt::Point(ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maFrom
.getToken( 0, ',', nIndex
), 0, true, true ),
754 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maFrom
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
756 aCoordLists
[ 0 ].push_back(
757 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl1
.getToken( 0, ',', nIndex
), 0, true, true ),
758 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl1
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
760 aCoordLists
[ 0 ].push_back(
761 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl2
.getToken( 0, ',', nIndex
), 0, true, true ),
762 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl2
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
764 aCoordLists
[ 0 ].push_back(
765 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maTo
.getToken( 0, ',', nIndex
), 0, true, true ),
766 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maTo
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
768 // First and last points are normals, points 2 and 4 are controls
769 aFlagLists
[ 0 ].resize( aCoordLists
[ 0 ].size(), PolygonFlags_CONTROL
);
770 aFlagLists
[ 0 ][ 0 ] = PolygonFlags_NORMAL
;
771 aFlagLists
[ 0 ].back() = PolygonFlags_NORMAL
;
773 // Curve defined by path attribute
776 // Parse VML path string and convert to absolute coordinates
777 ConversionHelper::decodeVmlPath( aCoordLists
, aFlagLists
, maShapeModel
.maVmlPath
);
779 for ( SubPathList::iterator aListIt
= aCoordLists
.begin(); aListIt
!= aCoordLists
.end(); ++aListIt
)
780 for ( ::std::vector
< awt::Point
>::iterator aPointIt
= (*aListIt
).begin(); aPointIt
!= (*aListIt
).end(); ++aPointIt
)
782 (*aPointIt
) = lclGetAbsPoint( (*aPointIt
), rShapeRect
, aCoordSys
);
786 aBezierCoords
.Coordinates
.realloc( aCoordLists
.size() );
787 for ( unsigned int i
= 0; i
< aCoordLists
.size(); i
++ )
788 aBezierCoords
.Coordinates
[i
] = ContainerHelper::vectorToSequence( aCoordLists
[i
] );
790 aBezierCoords
.Flags
.realloc( aFlagLists
.size() );
791 for ( unsigned int i
= 0; i
< aFlagLists
.size(); i
++ )
792 aBezierCoords
.Flags
[i
] = ContainerHelper::vectorToSequence( aFlagLists
[i
] );
794 if( !aCoordLists
.front().empty() && !aCoordLists
.back().empty()
795 && aCoordLists
.front().front().X
== aCoordLists
.back().back().X
796 && aCoordLists
.front().front().Y
== aCoordLists
.back().back().Y
)
797 { // HACK: If the shape is in fact closed, which can be found out only when the path is known,
798 // force to closed bezier shape (otherwise e.g. fill won't work).
799 const_cast< BezierShape
* >( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
803 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
805 if( aBezierCoords
.Coordinates
.hasElements())
807 PropertySet
aPropSet( xShape
);
808 aPropSet
.setProperty( PROP_PolyPolygonBezier
, aBezierCoords
);
811 // Hacky way of ensuring the shape is correctly sized/positioned
812 xShape
->setSize( awt::Size( rShapeRect
.Width
, rShapeRect
.Height
) );
813 xShape
->setPosition( awt::Point( rShapeRect
.X
, rShapeRect
.Y
) );
817 // ============================================================================
819 CustomShape::CustomShape( Drawing
& rDrawing
) :
820 SimpleShape( rDrawing
, "com.sun.star.drawing.CustomShape" )
824 Reference
< XShape
> CustomShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
826 // try to create a custom shape
827 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
828 if( xShape
.is() ) try
830 // create the custom shape geometry
831 Reference
< XEnhancedCustomShapeDefaulter
> xDefaulter( xShape
, UNO_QUERY_THROW
);
832 xDefaulter
->createCustomShapeDefaults( OUString::valueOf( getShapeType() ) );
833 // convert common properties
834 convertShapeProperties( xShape
);
842 // ============================================================================
844 ComplexShape::ComplexShape( Drawing
& rDrawing
) :
845 CustomShape( rDrawing
)
849 Reference
< XShape
> ComplexShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
851 XmlFilterBase
& rFilter
= mrDrawing
.getFilter();
852 sal_Int32 nShapeType
= getShapeType();
853 OUString aGraphicPath
= getGraphicPath();
855 // try to find registered OLE object info
856 if( const OleObjectInfo
* pOleObjectInfo
= mrDrawing
.getOleObjectInfo( maTypeModel
.maShapeId
) )
858 OSL_ENSURE( nShapeType
== VML_SHAPETYPE_PICTUREFRAME
, "ComplexShape::implConvertAndInsert - unexpected shape type" );
860 // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
861 if( pOleObjectInfo
->mbDmlShape
)
862 return Reference
< XShape
>();
864 PropertyMap aOleProps
;
865 awt::Size
aOleSize( rShapeRect
.Width
, rShapeRect
.Height
);
866 if( rFilter
.getOleObjectHelper().importOleObject( aOleProps
, *pOleObjectInfo
, aOleSize
) )
868 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.OLE2Shape", rxShapes
, rShapeRect
);
871 // set the replacement graphic
872 if( !aGraphicPath
.isEmpty() )
874 Reference
< XGraphic
> xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic( aGraphicPath
);
876 aOleProps
[ PROP_Graphic
] <<= xGraphic
;
879 PropertySet
aPropSet( xShape
);
880 aPropSet
.setProperties( aOleProps
);
887 // try to find registered form control info
888 const ControlInfo
* pControlInfo
= mrDrawing
.getControlInfo( maTypeModel
.maShapeId
);
889 if( pControlInfo
&& !pControlInfo
->maFragmentPath
.isEmpty() )
891 OSL_ENSURE( nShapeType
== VML_SHAPETYPE_HOSTCONTROL
, "ComplexShape::implConvertAndInsert - unexpected shape type" );
892 OUString aShapeName
= getShapeName();
893 if( !aShapeName
.isEmpty() )
895 OSL_ENSURE( aShapeName
== pControlInfo
->maName
, "ComplexShape::implConvertAndInsert - control name mismatch" );
896 // load the control properties from fragment
897 ::oox::ole::EmbeddedControl
aControl( aShapeName
);
898 if( rFilter
.importFragment( new ::oox::ole::AxControlFragment( rFilter
, pControlInfo
->maFragmentPath
, aControl
) ) )
900 // create and return the control shape (including control model)
901 sal_Int32 nCtrlIndex
= -1;
902 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXControlShape( aControl
, rxShapes
, rShapeRect
, nCtrlIndex
);
903 // on error, proceed and try to create picture from replacement image
910 // host application wants to create the shape (do not try failed OLE controls again)
911 if( (nShapeType
== VML_SHAPETYPE_HOSTCONTROL
) && !pControlInfo
)
913 OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
914 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertClientXShape( *this, rxShapes
, rShapeRect
);
919 // try to create a picture object
920 if( !aGraphicPath
.isEmpty() )
921 return SimpleShape::createPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
923 // default: try to create a custom shape
924 return CustomShape::implConvertAndInsert( rxShapes
, rShapeRect
);
927 // ============================================================================
929 GroupShape::GroupShape( Drawing
& rDrawing
) :
930 ShapeBase( rDrawing
),
931 mxChildren( new ShapeContainer( rDrawing
) )
935 GroupShape::~GroupShape()
939 void GroupShape::finalizeFragmentImport()
941 // basic shape processing
942 ShapeBase::finalizeFragmentImport();
943 // finalize all child shapes
944 mxChildren
->finalizeFragmentImport();
947 const ShapeType
* GroupShape::getChildTypeById( const OUString
& rShapeId
) const
949 return mxChildren
->getShapeTypeById( rShapeId
, true );
952 const ShapeBase
* GroupShape::getChildById( const OUString
& rShapeId
) const
954 return mxChildren
->getShapeById( rShapeId
, true );
957 Reference
< XShape
> GroupShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
959 Reference
< XShape
> xGroupShape
;
960 // check that this shape contains children and a valid coordinate system
961 ShapeParentAnchor aParentAnchor
;
962 aParentAnchor
.maShapeRect
= rShapeRect
;
963 aParentAnchor
.maCoordSys
= getCoordSystem();
964 if( !mxChildren
->empty() && (aParentAnchor
.maCoordSys
.Width
> 0) && (aParentAnchor
.maCoordSys
.Height
> 0) ) try
966 xGroupShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.GroupShape", rxShapes
, rShapeRect
);
967 Reference
< XShapes
> xChildShapes( xGroupShape
, UNO_QUERY_THROW
);
968 mxChildren
->convertAndInsert( xChildShapes
, &aParentAnchor
);
969 if( !xChildShapes
->hasElements() )
971 SAL_WARN("oox", "no child shape has been created - deleting the group shape");
972 rxShapes
->remove( xGroupShape
);
979 // Make sure group shapes are inline as well, unless there is an explicit different style.
980 PropertySet
aPropertySet(xGroupShape
);
981 lcl_SetAnchorType(aPropertySet
, maTypeModel
);
985 // ============================================================================
990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */