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"
24 #include <vcl/wmf.hxx>
26 #include <com/sun/star/beans/PropertyValues.hpp>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/awt/XControlModel.hpp>
29 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
30 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
31 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
32 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
33 #include <com/sun/star/drawing/XShapes.hpp>
34 #include <com/sun/star/drawing/XControlShape.hpp>
35 #include <com/sun/star/graphic/XGraphic.hpp>
36 #include <com/sun/star/table/BorderLine2.hpp>
37 #include <com/sun/star/text/HoriOrientation.hpp>
38 #include <com/sun/star/text/RelOrientation.hpp>
39 #include <com/sun/star/text/SizeType.hpp>
40 #include <com/sun/star/text/VertOrientation.hpp>
41 #include <com/sun/star/text/WrapTextMode.hpp>
42 #include <com/sun/star/text/XTextContent.hpp>
43 #include <com/sun/star/text/XTextDocument.hpp>
44 #include <com/sun/star/text/XTextFrame.hpp>
45 #include <com/sun/star/lang/XServiceInfo.hpp>
46 #include <com/sun/star/text/TextContentAnchorType.hpp>
47 #include <rtl/math.hxx>
48 #include <rtl/ustrbuf.hxx>
49 #include <svx/svdtrans.hxx>
50 #include "oox/drawingml/shapepropertymap.hxx"
51 #include "oox/helper/graphichelper.hxx"
52 #include "oox/helper/propertyset.hxx"
53 #include "oox/ole/axcontrol.hxx"
54 #include "oox/ole/axcontrolfragment.hxx"
55 #include "oox/ole/oleobjecthelper.hxx"
56 #include "oox/vml/vmldrawing.hxx"
57 #include "oox/vml/vmlshapecontainer.hxx"
58 #include "oox/vml/vmltextbox.hxx"
59 #include "oox/core/xmlfilterbase.hxx"
60 #include "oox/helper/containerhelper.hxx"
61 #include "svx/EnhancedCustomShapeTypeNames.hxx"
62 #include <svx/unoapi.hxx>
63 #include <svx/svdoashp.hxx>
65 using ::com::sun::star::beans::XPropertySet
;
66 using ::com::sun::star::uno::Any
;
68 using namespace ::com::sun::star
;
69 using namespace ::com::sun::star::text
;
74 using namespace ::com::sun::star
;
75 using namespace ::com::sun::star::drawing
;
76 using namespace ::com::sun::star::graphic
;
77 using namespace ::com::sun::star::uno
;
78 using namespace ::com::sun::star::io
;
80 using ::oox::core::XmlFilterBase
;
84 const sal_Int32 VML_SHAPETYPE_PICTUREFRAME
= 75;
85 const sal_Int32 VML_SHAPETYPE_HOSTCONTROL
= 201;
87 awt::Point
lclGetAbsPoint( const awt::Point
& rRelPoint
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
89 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
90 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
92 aAbsPoint
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelPoint
.X
- rCoordSys
.X
) + 0.5 );
93 aAbsPoint
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelPoint
.Y
- rCoordSys
.Y
) + 0.5 );
97 awt::Rectangle
lclGetAbsRect( const awt::Rectangle
& rRelRect
, const awt::Rectangle
& rShapeRect
, const awt::Rectangle
& rCoordSys
)
99 double fWidthRatio
= static_cast< double >( rShapeRect
.Width
) / rCoordSys
.Width
;
100 double fHeightRatio
= static_cast< double >( rShapeRect
.Height
) / rCoordSys
.Height
;
101 awt::Rectangle aAbsRect
;
102 aAbsRect
.X
= static_cast< sal_Int32
>( rShapeRect
.X
+ fWidthRatio
* (rRelRect
.X
- rCoordSys
.X
) + 0.5 );
103 aAbsRect
.Y
= static_cast< sal_Int32
>( rShapeRect
.Y
+ fHeightRatio
* (rRelRect
.Y
- rCoordSys
.Y
) + 0.5 );
104 aAbsRect
.Width
= static_cast< sal_Int32
>( fWidthRatio
* rRelRect
.Width
+ 0.5 );
105 aAbsRect
.Height
= static_cast< sal_Int32
>( fHeightRatio
* rRelRect
.Height
+ 0.5 );
111 ShapeTypeModel::ShapeTypeModel():
112 mbAutoHeight( false ),
117 void ShapeTypeModel::assignUsed( const ShapeTypeModel
& rSource
)
119 moShapeType
.assignIfUsed( rSource
.moShapeType
);
120 moCoordPos
.assignIfUsed( rSource
.moCoordPos
);
121 moCoordSize
.assignIfUsed( rSource
.moCoordSize
);
122 /* The style properties position, left, top, width, height, margin-left,
123 margin-top are not derived from shape template to shape. */
124 maStrokeModel
.assignUsed( rSource
.maStrokeModel
);
125 maFillModel
.assignUsed( rSource
.maFillModel
);
126 moGraphicPath
.assignIfUsed( rSource
.moGraphicPath
);
127 moGraphicTitle
.assignIfUsed( rSource
.moGraphicTitle
);
130 ShapeType::ShapeType( Drawing
& rDrawing
) :
131 mrDrawing( rDrawing
)
135 ShapeType::~ShapeType()
139 sal_Int32
ShapeType::getShapeType() const
141 return maTypeModel
.moShapeType
.get( 0 );
144 OUString
ShapeType::getGraphicPath() const
146 return maTypeModel
.moGraphicPath
.get( OUString() );
149 awt::Rectangle
ShapeType::getCoordSystem() const
151 Int32Pair aCoordPos
= maTypeModel
.moCoordPos
.get( Int32Pair( 0, 0 ) );
152 Int32Pair aCoordSize
= maTypeModel
.moCoordSize
.get( Int32Pair( 1000, 1000 ) );
153 if( aCoordSize
.first
== 0 )
154 aCoordSize
.first
= 1;
155 if( aCoordSize
.second
== 0 )
156 aCoordSize
.second
= 1;
157 return awt::Rectangle( aCoordPos
.first
, aCoordPos
.second
, aCoordSize
.first
, aCoordSize
.second
);
160 awt::Rectangle
ShapeType::getRectangle( const ShapeParentAnchor
* pParentAnchor
) const
162 return pParentAnchor
?
163 lclGetAbsRect( getRelRectangle(), pParentAnchor
->maShapeRect
, pParentAnchor
->maCoordSys
) :
167 awt::Rectangle
ShapeType::getAbsRectangle() const
169 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
171 sal_Int32 nWidth
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maWidth
, 0, true, true );
175 sal_Int32 nHeight
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maHeight
, 0, false, true );
179 sal_Int32 nLeft
= ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maLeft
, 0, true, true )
180 + ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maMarginLeft
, 0, true, true );
181 if (nLeft
== 0 && maTypeModel
.maPosition
== "absolute")
184 return awt::Rectangle(
186 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maTop
, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maTypeModel
.maMarginTop
, 0, false, true ),
190 awt::Rectangle
ShapeType::getRelRectangle() const
192 sal_Int32 nWidth
= maTypeModel
.maWidth
.toInt32();
196 sal_Int32 nHeight
= maTypeModel
.maHeight
.toInt32();
200 return awt::Rectangle(
201 maTypeModel
.maLeft
.toInt32(),
202 maTypeModel
.maTop
.toInt32(),
206 ClientData::ClientData() :
207 mnObjType( XML_TOKEN_INVALID
),
208 mnTextHAlign( XML_Left
),
209 mnTextVAlign( XML_Top
),
212 mnChecked( VML_CLIENTDATA_UNCHECKED
),
213 mnDropStyle( XML_Combo
),
220 mnSelType( XML_Single
),
221 mnVTEdit( VML_CLIENTDATA_TEXT
),
222 mbPrintObject( true ),
227 mbMultiLine( false ),
229 mbSecretEdit( false )
233 ShapeModel::ShapeModel()
237 ShapeModel::~ShapeModel()
241 TextBox
& ShapeModel::createTextBox(ShapeTypeModel
& rModel
)
243 mxTextBox
.reset( new TextBox(rModel
) );
247 ClientData
& ShapeModel::createClientData()
249 mxClientData
.reset( new ClientData
);
250 return *mxClientData
;
253 ShapeBase::ShapeBase( Drawing
& rDrawing
) :
254 ShapeType( rDrawing
)
258 void ShapeBase::finalizeFragmentImport()
260 if( maShapeModel
.maType
.getLength() > 1 )
262 OUString aType
= maShapeModel
.maType
;
263 if (aType
[ 0 ] == '#')
264 aType
= aType
.copy(1);
265 if( const ShapeType
* pShapeType
= mrDrawing
.getShapes().getShapeTypeById( aType
, true ) )
266 maTypeModel
.assignUsed( pShapeType
->getTypeModel() );
270 OUString
ShapeBase::getShapeName() const
272 if( !maTypeModel
.maShapeName
.isEmpty() )
273 return maTypeModel
.maShapeName
;
275 OUString aBaseName
= mrDrawing
.getShapeBaseName( *this );
276 if( !aBaseName
.isEmpty() )
278 sal_Int32 nShapeIdx
= mrDrawing
.getLocalShapeIndex( getShapeId() );
280 return OUStringBuffer( aBaseName
).append( ' ' ).append( nShapeIdx
).makeStringAndClear();
286 const ShapeType
* ShapeBase::getChildTypeById( const OUString
& ) const
291 const ShapeBase
* ShapeBase::getChildById( const OUString
& ) const
296 Reference
< XShape
> ShapeBase::convertAndInsert( const Reference
< XShapes
>& rxShapes
, const ShapeParentAnchor
* pParentAnchor
) const
298 Reference
< XShape
> xShape
;
299 if( mrDrawing
.isShapeSupported( *this ) )
301 /* Calculate shape rectangle. Applications may do something special
302 according to some imported shape client data (e.g. Excel cell anchor). */
303 awt::Rectangle aShapeRect
= calcShapeRectangle( pParentAnchor
);
305 if( ((aShapeRect
.Width
> 0) || (aShapeRect
.Height
> 0)) && rxShapes
.is() )
307 xShape
= implConvertAndInsert( rxShapes
, aShapeRect
);
310 // set imported or generated shape name (not supported by form controls)
311 PropertySet
aShapeProp( xShape
);
312 if( aShapeProp
.hasProperty( PROP_Name
) )
313 aShapeProp
.setProperty( PROP_Name
, getShapeName() );
314 uno::Reference
< lang::XServiceInfo
> xSInfo( xShape
, uno::UNO_QUERY_THROW
);
316 OUString sLinkChainName
= getTypeModel().maLegacyId
;
318 sal_Int32 idPos
= sLinkChainName
.indexOf("_x");
320 sal_Int32 seqPos
= sLinkChainName
.indexOf("_s",idPos
);
321 if( idPos
>= 0 && idPos
< seqPos
)
323 id
= sLinkChainName
.copy(idPos
+2,seqPos
-idPos
+2).toInt32();
324 seq
= sLinkChainName
.copy(seqPos
+2).toInt32();
327 OUString s_mso_next_textbox
;
329 s_mso_next_textbox
= getTextBox()->msNextTextbox
;
330 if( s_mso_next_textbox
.startsWith("#") )
331 s_mso_next_textbox
= s_mso_next_textbox
.copy(1);
333 if (xSInfo
->supportsService("com.sun.star.text.TextFrame"))
335 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
336 uno::Reference
<beans::XPropertySet
> propertySet (xShape
, uno::UNO_QUERY
);
337 propertySet
->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag
;
340 length
= aGrabBag
.getLength();
341 aGrabBag
.realloc( length
+1 );
342 aGrabBag
[length
].Name
= "VML-Z-ORDER";
343 aGrabBag
[length
].Value
= uno::makeAny( maTypeModel
.maZIndex
.toInt32() );
345 if( !s_mso_next_textbox
.isEmpty() )
347 length
= aGrabBag
.getLength();
348 aGrabBag
.realloc( length
+1 );
349 aGrabBag
[length
].Name
= "mso-next-textbox";
350 aGrabBag
[length
].Value
= uno::makeAny( s_mso_next_textbox
);
353 if( !sLinkChainName
.isEmpty() )
355 length
= aGrabBag
.getLength();
356 aGrabBag
.realloc( length
+4 );
357 aGrabBag
[length
].Name
= "TxbxHasLink";
358 aGrabBag
[length
].Value
= uno::makeAny( true );
359 aGrabBag
[length
+1].Name
= "Txbx-Id";
360 aGrabBag
[length
+1].Value
= uno::makeAny( id
);
361 aGrabBag
[length
+2].Name
= "Txbx-Seq";
362 aGrabBag
[length
+2].Value
= uno::makeAny( seq
);
363 aGrabBag
[length
+3].Name
= "LinkChainName";
364 aGrabBag
[length
+3].Value
= uno::makeAny( sLinkChainName
);
367 if(!(maTypeModel
.maRotation
).isEmpty())
369 length
= aGrabBag
.getLength();
370 aGrabBag
.realloc( length
+1 );
371 aGrabBag
[length
].Name
= "mso-rotation-angle";
372 aGrabBag
[length
].Value
= uno::makeAny(sal_Int32(NormAngle360((maTypeModel
.maRotation
.toInt32()) * -100)));
374 propertySet
->setPropertyValue( "FrameInteropGrabBag", uno::makeAny(aGrabBag
) );
375 sal_Int32 backColorTransparency
= 0;
376 propertySet
->getPropertyValue("BackColorTransparency")
377 >>= backColorTransparency
;
378 if (propertySet
->getPropertyValue("FillStyle") == FillStyle_NONE
&&
379 backColorTransparency
== 100)
381 // If there is no fill, the Word default is 100% transparency.
382 propertySet
->setPropertyValue("FillTransparence", makeAny(sal_Int16(100)));
387 if( maTypeModel
.maZIndex
.toInt32() )
389 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
390 uno::Reference
<beans::XPropertySet
> propertySet (xShape
, uno::UNO_QUERY
);
391 propertySet
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
394 length
= aGrabBag
.getLength();
395 aGrabBag
.realloc( length
+1 );
396 aGrabBag
[length
].Name
= "VML-Z-ORDER";
397 aGrabBag
[length
].Value
= uno::makeAny( maTypeModel
.maZIndex
.toInt32() );
399 if( !s_mso_next_textbox
.isEmpty() )
401 length
= aGrabBag
.getLength();
402 aGrabBag
.realloc( length
+1 );
403 aGrabBag
[length
].Name
= "mso-next-textbox";
404 aGrabBag
[length
].Value
= uno::makeAny( s_mso_next_textbox
);
407 if( !sLinkChainName
.isEmpty() )
409 length
= aGrabBag
.getLength();
410 aGrabBag
.realloc( length
+4 );
411 aGrabBag
[length
].Name
= "TxbxHasLink";
412 aGrabBag
[length
].Value
= uno::makeAny( true );
413 aGrabBag
[length
+1].Name
= "Txbx-Id";
414 aGrabBag
[length
+1].Value
= uno::makeAny( id
);
415 aGrabBag
[length
+2].Name
= "Txbx-Seq";
416 aGrabBag
[length
+2].Value
= uno::makeAny( seq
);
417 aGrabBag
[length
+3].Name
= "LinkChainName";
418 aGrabBag
[length
+3].Value
= uno::makeAny( sLinkChainName
);
420 propertySet
->setPropertyValue( "InteropGrabBag", uno::makeAny(aGrabBag
) );
423 Reference
< XControlShape
> xControlShape( xShape
, uno::UNO_QUERY
);
424 if ( xControlShape
.is() && !getTypeModel().mbVisible
)
426 PropertySet
aControlShapeProp( xControlShape
->getControl() );
427 aControlShapeProp
.setProperty( PROP_EnableVisible
, uno::makeAny( sal_False
) );
429 /* Notify the drawing that a new shape has been inserted. For
430 convenience, pass the rectangle that contains position and
431 size of the shape. */
432 bool bGroupChild
= pParentAnchor
!= 0;
433 mrDrawing
.notifyXShapeInserted( xShape
, aShapeRect
, *this, bGroupChild
);
437 SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
442 void ShapeBase::convertFormatting( const Reference
< XShape
>& rxShape
, const ShapeParentAnchor
* pParentAnchor
) const
446 /* Calculate shape rectangle. Applications may do something special
447 according to some imported shape client data (e.g. Excel cell anchor). */
448 awt::Rectangle aShapeRect
= calcShapeRectangle( pParentAnchor
);
450 // convert the shape, if the calculated rectangle is not empty
451 if( (aShapeRect
.Width
> 0) || (aShapeRect
.Height
> 0) )
453 rxShape
->setPosition( awt::Point( aShapeRect
.X
, aShapeRect
.Y
) );
454 rxShape
->setSize( awt::Size( aShapeRect
.Width
, aShapeRect
.Height
) );
455 convertShapeProperties( rxShape
);
460 // protected ------------------------------------------------------------------
462 awt::Rectangle
ShapeBase::calcShapeRectangle( const ShapeParentAnchor
* pParentAnchor
) const
464 /* Calculate shape rectangle. Applications may do something special
465 according to some imported shape client data (e.g. Excel cell anchor). */
466 awt::Rectangle aShapeRect
;
467 const ClientData
* pClientData
= getClientData();
468 if( !pClientData
|| !mrDrawing
.convertClientAnchor( aShapeRect
, pClientData
->maAnchor
) )
469 aShapeRect
= getRectangle( pParentAnchor
);
473 void ShapeBase::convertShapeProperties( const Reference
< XShape
>& rxShape
) const
475 ::oox::drawingml::ShapePropertyMap
aPropMap( mrDrawing
.getFilter().getModelObjectHelper() );
476 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
477 maTypeModel
.maStrokeModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
478 maTypeModel
.maFillModel
.pushToPropMap( aPropMap
, rGraphicHelper
);
480 uno::Reference
<lang::XServiceInfo
> xSInfo(rxShape
, uno::UNO_QUERY_THROW
);
481 if (xSInfo
->supportsService("com.sun.star.text.TextFrame"))
483 // Any other service supporting the ShadowFormat property?
484 maTypeModel
.maShadowModel
.pushToPropMap(aPropMap
, rGraphicHelper
);
485 // TextFrames have BackColor, not FillColor
486 if (aPropMap
.hasProperty(PROP_FillColor
))
488 aPropMap
.setAnyProperty(PROP_BackColor
, aPropMap
.getProperty(PROP_FillColor
));
489 aPropMap
.erase(PROP_FillColor
);
491 // TextFrames have BackColorTransparency, not FillTransparence
492 if (aPropMap
.hasProperty(PROP_FillTransparence
))
494 aPropMap
.setAnyProperty(PROP_BackColorTransparency
, aPropMap
.getProperty(PROP_FillTransparence
));
495 aPropMap
.erase(PROP_FillTransparence
);
497 // And no LineColor property; individual borders can have colors and widths
498 boost::optional
<sal_Int32
> oLineWidth
;
499 if (maTypeModel
.maStrokeModel
.moWeight
.has())
500 oLineWidth
.reset(ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maStrokeModel
.moWeight
.get(), 0, false, false));
501 if (aPropMap
.hasProperty(PROP_LineColor
))
503 uno::Reference
<beans::XPropertySet
> xPropertySet(rxShape
, uno::UNO_QUERY
);
504 static const sal_Int32 aBorders
[] = {
505 PROP_TopBorder
, PROP_LeftBorder
, PROP_BottomBorder
, PROP_RightBorder
507 for (unsigned int i
= 0; i
< SAL_N_ELEMENTS(aBorders
); ++i
)
509 table::BorderLine2 aBorderLine
= xPropertySet
->getPropertyValue(PropertyMap::getPropertyName(aBorders
[i
])).get
<table::BorderLine2
>();
510 aBorderLine
.Color
= aPropMap
.getProperty(PROP_LineColor
).get
<sal_Int32
>();
512 aBorderLine
.LineWidth
= *oLineWidth
;
513 aPropMap
.setProperty(aBorders
[i
], uno::makeAny(aBorderLine
));
515 aPropMap
.erase(PROP_LineColor
);
518 else if (xSInfo
->supportsService("com.sun.star.drawing.CustomShape"))
519 maTypeModel
.maTextpathModel
.pushToPropMap(aPropMap
, rxShape
);
521 PropertySet( rxShape
).setProperties( aPropMap
);
524 SimpleShape::SimpleShape( Drawing
& rDrawing
, const OUString
& rService
) :
525 ShapeBase( rDrawing
),
526 maService( rService
)
530 void lcl_setSurround(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
, const GraphicHelper
& rGraphicHelper
)
532 OUString aWrapType
= rTypeModel
.moWrapType
.get();
534 // Extreme negative top margin? Then the shape will end up at the top of the page, it's pointless to perform any kind of wrapping.
535 sal_Int32 nMarginTop
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, rTypeModel
.maMarginTop
, 0, false, true);
536 if (nMarginTop
< -35277) // Less than 1000 points.
539 sal_Int32 nSurround
= com::sun::star::text::WrapTextMode_THROUGHT
;
540 if ( aWrapType
== "square" || aWrapType
== "tight" ||
541 aWrapType
== "through" )
543 nSurround
= com::sun::star::text::WrapTextMode_PARALLEL
;
544 if ( rTypeModel
.moWrapSide
.get() == "left" )
545 nSurround
= com::sun::star::text::WrapTextMode_LEFT
;
546 else if ( rTypeModel
.moWrapSide
.get() == "right" )
547 nSurround
= com::sun::star::text::WrapTextMode_RIGHT
;
549 else if ( aWrapType
== "topAndBottom" )
550 nSurround
= com::sun::star::text::WrapTextMode_NONE
;
552 rPropSet
.setProperty(PROP_Surround
, nSurround
);
555 void lcl_SetAnchorType(PropertySet
& rPropSet
, const ShapeTypeModel
& rTypeModel
, const GraphicHelper
& rGraphicHelper
)
557 if ( rTypeModel
.maPositionHorizontal
== "center" )
558 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::CENTER
));
559 else if ( rTypeModel
.maPositionHorizontal
== "left" )
560 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::LEFT
));
561 else if ( rTypeModel
.maPositionHorizontal
== "right" )
562 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::RIGHT
));
563 else if ( rTypeModel
.maPositionHorizontal
== "inside" )
565 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::LEFT
));
566 rPropSet
.setAnyProperty(PROP_PageToggle
, makeAny(sal_True
));
568 else if ( rTypeModel
.maPositionHorizontal
== "outside" )
570 rPropSet
.setAnyProperty(PROP_HoriOrient
, makeAny(text::HoriOrientation::RIGHT
));
571 rPropSet
.setAnyProperty(PROP_PageToggle
, makeAny(sal_True
));
574 if ( rTypeModel
.maPositionHorizontalRelative
== "page" )
575 rPropSet
.setAnyProperty(PROP_HoriOrientRelation
, makeAny(text::RelOrientation::PAGE_FRAME
));
576 else if ( rTypeModel
.maPositionVerticalRelative
== "margin" )
577 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA
);
578 else if ( rTypeModel
.maPositionVerticalRelative
== "text" )
579 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::FRAME
);
581 if ( rTypeModel
.maPositionVertical
== "center" )
582 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::CENTER
));
583 else if ( rTypeModel
.maPositionVertical
== "top" )
584 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::TOP
));
585 else if ( rTypeModel
.maPositionVertical
== "bottom" )
586 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::BOTTOM
));
587 else if ( rTypeModel
.maPositionVertical
== "inside" )
588 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::LINE_TOP
));
589 else if ( rTypeModel
.maPositionVertical
== "outside" )
590 rPropSet
.setAnyProperty(PROP_VertOrient
, makeAny(text::VertOrientation::LINE_BOTTOM
));
592 if ( rTypeModel
.maPosition
== "absolute" )
594 // Word supports as-character (inline) and at-character only, absolute can't be inline.
595 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_CHARACTER
);
597 if ( rTypeModel
.maPositionVerticalRelative
== "page" )
599 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_FRAME
);
601 else if ( rTypeModel
.maPositionVerticalRelative
== "margin" )
603 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::PAGE_PRINT_AREA
);
607 rPropSet
.setProperty(PROP_VertOrientRelation
, text::RelOrientation::FRAME
);
610 else if( rTypeModel
.maPosition
== "relative" )
611 { // I'm not very sure this is correct either.
612 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AT_PARAGRAPH
);
614 else // static (is the default) means anchored inline
616 rPropSet
.setProperty(PROP_AnchorType
, text::TextContentAnchorType_AS_CHARACTER
);
618 lcl_setSurround( rPropSet
, rTypeModel
, rGraphicHelper
);
621 void lcl_SetRotation(PropertySet
& rPropSet
, const sal_Int32 nRotation
)
623 // See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation angles are clockwise, we have them as counter-clockwise.
624 // Additionally, VML type is 0..360, our is 0..36000.
625 rPropSet
.setAnyProperty(PROP_RotateAngle
, makeAny(sal_Int32(NormAngle360(nRotation
* -100))));
628 Reference
< XShape
> SimpleShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
630 awt::Rectangle
aShapeRect(rShapeRect
);
631 boost::optional
<sal_Int32
> oRotation
;
632 bool bFlipX
= false, bFlipY
= false;
633 if (!maTypeModel
.maRotation
.isEmpty())
634 oRotation
.reset(maTypeModel
.maRotation
.toInt32());
635 if (!maTypeModel
.maFlip
.isEmpty())
637 if (maTypeModel
.maFlip
== "x")
641 else if (maTypeModel
.maFlip
== "y")
647 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( maService
, rxShapes
, aShapeRect
);
648 SdrObject
* pShape
= GetSdrObjectFromXShape( xShape
);
649 if( pShape
&& getShapeType() >= 0 )
652 aShapeType
= EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT
>(getShapeType()) );
653 //The resize autoshape to fit text attr of FontWork/Word-Art should always be false
654 //for the fallback geometry.
655 if(aShapeType
.startsWith("fontwork"))
657 pShape
->SetMergedItem(makeSdrTextAutoGrowHeightItem(false));
658 pShape
->SetMergedItem(makeSdrTextAutoGrowWidthItem(false));
661 convertShapeProperties( xShape
);
663 // Handle left/right/top/bottom wrap distance.
664 // Default value of mso-wrap-distance-left/right is supposed to be 0 (see
665 // 19.1.2.19 of the VML spec), but Word implements a non-zero value.
666 // [MS-ODRAW] says the below default value in 2.3.4.9.
667 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
668 OUString aWrapDistanceLeft
= OUString::number(0x0001BE7C);
669 if (!maTypeModel
.maWrapDistanceLeft
.isEmpty())
670 aWrapDistanceLeft
= maTypeModel
.maWrapDistanceLeft
;
671 sal_Int32 nWrapDistanceLeft
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, aWrapDistanceLeft
, 0, true, false);
672 PropertySet(xShape
).setAnyProperty(PROP_LeftMargin
, uno::makeAny(nWrapDistanceLeft
));
673 OUString aWrapDistanceRight
= OUString::number(0x0001BE7C);
674 if (!maTypeModel
.maWrapDistanceRight
.isEmpty())
675 aWrapDistanceRight
= maTypeModel
.maWrapDistanceRight
;
676 sal_Int32 nWrapDistanceRight
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, aWrapDistanceRight
, 0, true, false);
677 PropertySet(xShape
).setAnyProperty(PROP_RightMargin
, uno::makeAny(nWrapDistanceRight
));
678 sal_Int32 nWrapDistanceTop
= 0;
679 if (!maTypeModel
.maWrapDistanceTop
.isEmpty())
680 nWrapDistanceTop
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceTop
, 0, false, true);
681 PropertySet(xShape
).setAnyProperty(PROP_TopMargin
, uno::makeAny(nWrapDistanceTop
));
682 sal_Int32 nWrapDistanceBottom
= 0;
683 if (!maTypeModel
.maWrapDistanceBottom
.isEmpty())
684 nWrapDistanceBottom
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maTypeModel
.maWrapDistanceBottom
, 0, false, true);
685 PropertySet(xShape
).setAnyProperty(PROP_BottomMargin
, uno::makeAny(nWrapDistanceBottom
));
687 if ( maService
== "com.sun.star.text.TextFrame" )
689 PropertySet( xShape
).setAnyProperty( PROP_FrameIsAutomaticHeight
, makeAny( maTypeModel
.mbAutoHeight
) );
690 PropertySet( xShape
).setAnyProperty( PROP_SizeType
, makeAny( maTypeModel
.mbAutoHeight
? SizeType::MIN
: SizeType::FIX
) );
691 if( getTextBox()->borderDistanceSet
)
693 PropertySet( xShape
).setAnyProperty( PROP_LeftBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceLeft
)));
694 PropertySet( xShape
).setAnyProperty( PROP_TopBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceTop
)));
695 PropertySet( xShape
).setAnyProperty( PROP_RightBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceRight
)));
696 PropertySet( xShape
).setAnyProperty( PROP_BottomBorderDistance
, makeAny( sal_Int32( getTextBox()->borderDistanceBottom
)));
698 if (!maTypeModel
.maLayoutFlowAlt
.isEmpty())
700 // Can't handle this property here, as the frame is not attached yet: pass it to writerfilter.
701 uno::Reference
<beans::XPropertySet
> xPropertySet(xShape
, uno::UNO_QUERY
);
702 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
703 xPropertySet
->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag
;
704 beans::PropertyValue aPair
;
705 aPair
.Name
= "mso-layout-flow-alt";
706 aPair
.Value
= uno::makeAny(maTypeModel
.maLayoutFlowAlt
);
707 if (aGrabBag
.hasElements())
709 sal_Int32 nLength
= aGrabBag
.getLength();
710 aGrabBag
.realloc(nLength
+ 1);
711 aGrabBag
[nLength
] = aPair
;
718 xPropertySet
->setPropertyValue("FrameInteropGrabBag", uno::makeAny(aGrabBag
));
723 // FIXME Setting the relative width/heigh only for everything but text frames as
724 // TextFrames already have relative width/height feature... but currently not working
725 // in the way we need.
727 // Set the relative width / height if any
728 if ( !maTypeModel
.maWidthPercent
.isEmpty( ) )
730 // Only page-relative width is supported ATM
731 if ( maTypeModel
.maWidthRelative
.isEmpty() || maTypeModel
.maWidthRelative
== "page" )
733 sal_Int16 nWidth
= maTypeModel
.maWidthPercent
.toInt32() / 10;
734 // Only apply if nWidth != 0
736 PropertySet( xShape
).setAnyProperty(PROP_RelativeWidth
, makeAny( nWidth
) );
739 if ( !maTypeModel
.maHeightPercent
.isEmpty( ) )
741 // Only page-relative height is supported ATM
742 if ( maTypeModel
.maHeightRelative
.isEmpty() || maTypeModel
.maHeightRelative
== "page" )
744 sal_Int16 nHeight
= maTypeModel
.maHeightPercent
.toInt32() / 10;
745 // Only apply if nHeight != 0
747 PropertySet( xShape
).setAnyProperty(PROP_RelativeHeight
, makeAny( nHeight
) );
751 // drawinglayer default is center, MSO default is top.
752 drawing::TextVerticalAdjust eTextVerticalAdjust
= drawing::TextVerticalAdjust_TOP
;
753 if (maTypeModel
.maVTextAnchor
== "middle")
754 eTextVerticalAdjust
= drawing::TextVerticalAdjust_CENTER
;
755 else if (maTypeModel
.maVTextAnchor
== "bottom")
756 eTextVerticalAdjust
= drawing::TextVerticalAdjust_BOTTOM
;
757 PropertySet(xShape
).setAnyProperty(PROP_TextVerticalAdjust
, makeAny(eTextVerticalAdjust
));
761 getTextBox()->convert(xShape
);
762 if (getTextBox()->borderDistanceSet
)
764 awt::Size aSize
= xShape
->getSize();
765 PropertySet(xShape
).setAnyProperty(PROP_TextLeftDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceLeft
)));
766 PropertySet(xShape
).setAnyProperty(PROP_TextUpperDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceTop
)));
767 PropertySet(xShape
).setAnyProperty(PROP_TextRightDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceRight
)));
768 PropertySet(xShape
).setAnyProperty(PROP_TextLowerDistance
, makeAny(sal_Int32(getTextBox()->borderDistanceBottom
)));
769 xShape
->setSize(aSize
);
774 // Import Legacy Fragments (if any)
775 if( xShape
.is() && !maShapeModel
.maLegacyDiagramPath
.isEmpty() )
777 Reference
< XInputStream
> xInStrm( mrDrawing
.getFilter().openInputStream( maShapeModel
.maLegacyDiagramPath
), UNO_SET_THROW
);
779 PropertySet( xShape
).setProperty( PROP_LegacyFragment
, xInStrm
);
782 PropertySet
aPropertySet(xShape
);
787 lcl_SetRotation(aPropertySet
, *oRotation
);
788 uno::Reference
<lang::XServiceInfo
> xServiceInfo(rxShapes
, uno::UNO_QUERY
);
789 if (!xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape"))
791 // If rotation is used, simple setPosition() is not enough.
792 aPropertySet
.setAnyProperty(PROP_HoriOrientPosition
, makeAny(aShapeRect
.X
));
793 aPropertySet
.setAnyProperty(PROP_VertOrientPosition
, makeAny(aShapeRect
.Y
));
797 // When flip has 'x' or 'y', the associated ShapeRect will be changed but direction change doesn't occur.
798 // It might occur internally in SdrObject of "sw" module, not here.
799 // The associated properties "PROP_MirroredX" and "PROP_MirroredY" have to be set here so that direction change will occur internally.
800 if (bFlipX
|| bFlipY
)
802 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aPropSequence (2);
803 int nPropertyIndex
= 0;
806 aPropSequence
[nPropertyIndex
].Name
= "MirroredX";
807 aPropSequence
[nPropertyIndex
].Value
= makeAny (bFlipX
);
812 aPropSequence
[nPropertyIndex
].Name
= "MirroredY";
813 aPropSequence
[nPropertyIndex
].Value
= makeAny (bFlipY
);
816 aPropertySet
.setAnyProperty(PROP_CustomShapeGeometry
, makeAny( aPropSequence
) );
820 lcl_SetAnchorType(aPropertySet
, maTypeModel
, rGraphicHelper
);
825 Reference
< XShape
> SimpleShape::createPictureObject( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
, OUString
& rGraphicPath
) const
827 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.GraphicObjectShape", rxShapes
, rShapeRect
);
830 XmlFilterBase
& rFilter
= mrDrawing
.getFilter();
831 OUString aGraphicUrl
= rFilter
.getGraphicHelper().importEmbeddedGraphicObject( rGraphicPath
);
832 PropertySet
aPropSet( xShape
);
833 if( !aGraphicUrl
.isEmpty() )
835 aPropSet
.setProperty( PROP_GraphicURL
, aGraphicUrl
);
837 uno::Reference
< lang::XServiceInfo
> xServiceInfo(rxShapes
, uno::UNO_QUERY
);
838 // If the shape has an absolute position, set the properties accordingly, unless we're inside a group shape.
839 if ( maTypeModel
.maPosition
== "absolute" && !xServiceInfo
->supportsService("com.sun.star.drawing.GroupShape"))
841 aPropSet
.setProperty(PROP_HoriOrientPosition
, rShapeRect
.X
);
842 aPropSet
.setProperty(PROP_VertOrientPosition
, rShapeRect
.Y
);
843 aPropSet
.setProperty(PROP_Opaque
, sal_False
);
845 // fdo#70457: preserve rotation information
846 if ( !maTypeModel
.maRotation
.isEmpty() )
847 lcl_SetRotation( aPropSet
, maTypeModel
.maRotation
.toInt32() );
849 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
850 lcl_SetAnchorType(aPropSet
, maTypeModel
, rGraphicHelper
);
855 RectangleShape::RectangleShape( Drawing
& rDrawing
) :
856 SimpleShape( rDrawing
, "com.sun.star.drawing.RectangleShape" )
860 Reference
<XShape
> RectangleShape::implConvertAndInsert(const Reference
<XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
862 OUString aGraphicPath
= getGraphicPath();
864 // try to create a picture object
865 if(!aGraphicPath
.isEmpty())
866 return SimpleShape::createPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
868 // default: try to create a rectangle shape
869 Reference
<XShape
> xShape
= SimpleShape::implConvertAndInsert(rxShapes
, rShapeRect
);
870 OUString sArcsize
= maTypeModel
.maArcsize
;
871 if ( !sArcsize
.isEmpty( ) )
873 sal_Unicode cLastChar
= sArcsize
[sArcsize
.getLength() - 1];
874 sal_Int32 nValue
= sArcsize
.copy( 0, sArcsize
.getLength() - 1 ).toInt32( );
875 // Get the smallest half-side
876 double size
= std::min( rShapeRect
.Height
, rShapeRect
.Width
) / 2.0;
877 sal_Int32 nRadius
= 0;
878 if ( cLastChar
== 'f' )
879 nRadius
= size
* nValue
/ 65536;
880 else if ( cLastChar
== '%' )
881 nRadius
= size
* nValue
/ 100;
882 PropertySet( xShape
).setAnyProperty( PROP_CornerRadius
, makeAny( nRadius
) );
887 EllipseShape::EllipseShape( Drawing
& rDrawing
) :
888 SimpleShape( rDrawing
, "com.sun.star.drawing.EllipseShape" )
892 PolyLineShape::PolyLineShape( Drawing
& rDrawing
) :
893 SimpleShape( rDrawing
, "com.sun.star.drawing.PolyLineShape" )
897 Reference
< XShape
> PolyLineShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
899 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
901 awt::Rectangle aCoordSys
= getCoordSystem();
902 if( !maShapeModel
.maPoints
.empty() && (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0) )
904 ::std::vector
< awt::Point
> aAbsPoints
;
905 for( ShapeModel::PointVector::const_iterator aIt
= maShapeModel
.maPoints
.begin(), aEnd
= maShapeModel
.maPoints
.end(); aIt
!= aEnd
; ++aIt
)
906 aAbsPoints
.push_back( lclGetAbsPoint( *aIt
, rShapeRect
, aCoordSys
) );
907 PointSequenceSequence
aPointSeq( 1 );
908 aPointSeq
[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints
);
909 PropertySet
aPropSet( xShape
);
910 aPropSet
.setProperty( PROP_PolyPolygon
, aPointSeq
);
915 LineShape::LineShape(Drawing
& rDrawing
)
916 : SimpleShape(rDrawing
, "com.sun.star.drawing.LineShape")
920 awt::Rectangle
LineShape::getAbsRectangle() const
922 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
923 awt::Rectangle aShapeRect
;
924 sal_Int32 nIndex
= 0;
926 aShapeRect
.X
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maFrom
.getToken(0, ',', nIndex
), 0, true, true);
927 aShapeRect
.Y
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maFrom
.getToken(0, ',', nIndex
), 0, false, true);
929 aShapeRect
.Width
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maTo
.getToken(0, ',', nIndex
), 0, true, true) - aShapeRect
.X
;
930 aShapeRect
.Height
= ConversionHelper::decodeMeasureToHmm(rGraphicHelper
, maShapeModel
.maTo
.getToken(0, ',', nIndex
), 0, false, true) - aShapeRect
.Y
;
934 awt::Rectangle
LineShape::getRelRectangle() const
936 awt::Rectangle aShapeRect
;
937 sal_Int32 nIndex
= 0;
939 aShapeRect
.X
= maShapeModel
.maFrom
.getToken(0, ',', nIndex
).toInt32();
940 aShapeRect
.Y
= maShapeModel
.maFrom
.getToken(0, ',', nIndex
).toInt32();
942 aShapeRect
.Width
= maShapeModel
.maTo
.getToken(0, ',', nIndex
).toInt32() - aShapeRect
.X
;
943 aShapeRect
.Height
= maShapeModel
.maTo
.getToken(0, ',', nIndex
).toInt32() - aShapeRect
.Y
;
947 BezierShape::BezierShape(Drawing
& rDrawing
)
948 : SimpleShape(rDrawing
, "com.sun.star.drawing.OpenBezierShape")
952 Reference
< XShape
> BezierShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
954 // If we have an 'x' in the last part of the path it means it is closed...
955 sal_Int32 nPos
= maShapeModel
.maVmlPath
.lastIndexOf(',');
956 if ( nPos
!= -1 && maShapeModel
.maVmlPath
.copy(nPos
).indexOf('x') != -1 )
958 const_cast<BezierShape
*>( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
961 awt::Rectangle aCoordSys
= getCoordSystem();
962 PolyPolygonBezierCoords aBezierCoords
;
964 if( (aCoordSys
.Width
> 0) && (aCoordSys
.Height
> 0) )
966 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
968 // Bezier paths may consist of one or more sub-paths
969 typedef ::std::vector
< ::std::vector
< awt::Point
> > SubPathList
;
970 typedef ::std::vector
< ::std::vector
< PolygonFlags
> > FlagsList
;
971 SubPathList aCoordLists
;
972 FlagsList aFlagLists
;
973 sal_Int32 nIndex
= 0;
975 // Curve defined by to, from, control1 and control2 attributes
976 if ( maShapeModel
.maVmlPath
.isEmpty() )
978 aCoordLists
.push_back( ::std::vector
< awt::Point
>() );
979 aFlagLists
.push_back( ::std::vector
< PolygonFlags
>() );
982 aCoordLists
[ 0 ].push_back(
983 awt::Point(ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maFrom
.getToken( 0, ',', nIndex
), 0, true, true ),
984 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maFrom
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
986 aCoordLists
[ 0 ].push_back(
987 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl1
.getToken( 0, ',', nIndex
), 0, true, true ),
988 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl1
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
990 aCoordLists
[ 0 ].push_back(
991 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl2
.getToken( 0, ',', nIndex
), 0, true, true ),
992 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maControl2
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
994 aCoordLists
[ 0 ].push_back(
995 awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maTo
.getToken( 0, ',', nIndex
), 0, true, true ),
996 ConversionHelper::decodeMeasureToHmm( rGraphicHelper
, maShapeModel
.maTo
.getToken( 0, ',', nIndex
), 0, false, true ) ) );
998 // First and last points are normals, points 2 and 4 are controls
999 aFlagLists
[ 0 ].resize( aCoordLists
[ 0 ].size(), PolygonFlags_CONTROL
);
1000 aFlagLists
[ 0 ][ 0 ] = PolygonFlags_NORMAL
;
1001 aFlagLists
[ 0 ].back() = PolygonFlags_NORMAL
;
1003 // Curve defined by path attribute
1006 // Parse VML path string and convert to absolute coordinates
1007 ConversionHelper::decodeVmlPath( aCoordLists
, aFlagLists
, maShapeModel
.maVmlPath
);
1009 for ( SubPathList::iterator aListIt
= aCoordLists
.begin(); aListIt
!= aCoordLists
.end(); ++aListIt
)
1010 for ( ::std::vector
< awt::Point
>::iterator aPointIt
= (*aListIt
).begin(); aPointIt
!= (*aListIt
).end(); ++aPointIt
)
1012 (*aPointIt
) = lclGetAbsPoint( (*aPointIt
), rShapeRect
, aCoordSys
);
1016 aBezierCoords
.Coordinates
.realloc( aCoordLists
.size() );
1017 for ( unsigned int i
= 0; i
< aCoordLists
.size(); i
++ )
1018 aBezierCoords
.Coordinates
[i
] = ContainerHelper::vectorToSequence( aCoordLists
[i
] );
1020 aBezierCoords
.Flags
.realloc( aFlagLists
.size() );
1021 for ( unsigned int i
= 0; i
< aFlagLists
.size(); i
++ )
1022 aBezierCoords
.Flags
[i
] = ContainerHelper::vectorToSequence( aFlagLists
[i
] );
1024 if( !aCoordLists
.front().empty() && !aCoordLists
.back().empty()
1025 && aCoordLists
.front().front().X
== aCoordLists
.back().back().X
1026 && aCoordLists
.front().front().Y
== aCoordLists
.back().back().Y
)
1027 { // HACK: If the shape is in fact closed, which can be found out only when the path is known,
1028 // force to closed bezier shape (otherwise e.g. fill won't work).
1029 const_cast< BezierShape
* >( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
1033 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1035 if( aBezierCoords
.Coordinates
.hasElements())
1037 PropertySet
aPropSet( xShape
);
1038 aPropSet
.setProperty( PROP_PolyPolygonBezier
, aBezierCoords
);
1041 // Hacky way of ensuring the shape is correctly sized/positioned
1042 xShape
->setSize( awt::Size( rShapeRect
.Width
, rShapeRect
.Height
) );
1043 xShape
->setPosition( awt::Point( rShapeRect
.X
, rShapeRect
.Y
) );
1047 CustomShape::CustomShape( Drawing
& rDrawing
) :
1048 SimpleShape( rDrawing
, "com.sun.star.drawing.CustomShape" )
1052 Reference
< XShape
> CustomShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1054 // try to create a custom shape
1055 Reference
< XShape
> xShape
= SimpleShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1056 if( xShape
.is() ) try
1058 // create the custom shape geometry
1059 Reference
< XEnhancedCustomShapeDefaulter
> xDefaulter( xShape
, UNO_QUERY_THROW
);
1060 xDefaulter
->createCustomShapeDefaults( OUString::number( getShapeType() ) );
1061 // convert common properties
1062 convertShapeProperties( xShape
);
1070 ComplexShape::ComplexShape( Drawing
& rDrawing
) :
1071 CustomShape( rDrawing
)
1075 Reference
< XShape
> ComplexShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1077 XmlFilterBase
& rFilter
= mrDrawing
.getFilter();
1078 sal_Int32 nShapeType
= getShapeType();
1079 OUString aGraphicPath
= getGraphicPath();
1081 // try to find registered OLE object info
1082 if( const OleObjectInfo
* pOleObjectInfo
= mrDrawing
.getOleObjectInfo( maTypeModel
.maShapeId
) )
1085 nShapeType
!= VML_SHAPETYPE_PICTUREFRAME
, "oox",
1086 "ComplexShape::implConvertAndInsert - unexpected shape type");
1088 // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
1089 if( pOleObjectInfo
->mbDmlShape
)
1090 return Reference
< XShape
>();
1092 PropertyMap aOleProps
;
1093 awt::Size
aOleSize( rShapeRect
.Width
, rShapeRect
.Height
);
1094 if( rFilter
.getOleObjectHelper().importOleObject( aOleProps
, *pOleObjectInfo
, aOleSize
) )
1096 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.OLE2Shape", rxShapes
, rShapeRect
);
1099 // set the replacement graphic
1100 if( !aGraphicPath
.isEmpty() )
1102 WMF_EXTERNALHEADER aExtHeader
;
1103 aExtHeader
.mapMode
= 8;
1104 aExtHeader
.xExt
= rShapeRect
.Width
;
1105 aExtHeader
.yExt
= rShapeRect
.Height
;
1107 Reference
< XGraphic
> xGraphic
= rFilter
.getGraphicHelper().importEmbeddedGraphic(aGraphicPath
, &aExtHeader
);
1109 aOleProps
.setProperty( PROP_Graphic
, xGraphic
);
1112 PropertySet
aPropSet( xShape
);
1113 aPropSet
.setProperties( aOleProps
);
1120 // try to find registered form control info
1121 const ControlInfo
* pControlInfo
= mrDrawing
.getControlInfo( maTypeModel
.maShapeId
);
1122 if( pControlInfo
&& !pControlInfo
->maFragmentPath
.isEmpty() )
1124 OSL_ENSURE( nShapeType
== VML_SHAPETYPE_HOSTCONTROL
, "ComplexShape::implConvertAndInsert - unexpected shape type" );
1125 OUString aShapeName
= getShapeName();
1126 if( !aShapeName
.isEmpty() )
1128 OSL_ENSURE( aShapeName
== pControlInfo
->maName
, "ComplexShape::implConvertAndInsert - control name mismatch" );
1129 // load the control properties from fragment
1130 ::oox::ole::EmbeddedControl
aControl( aShapeName
);
1131 if( rFilter
.importFragment( new ::oox::ole::AxControlFragment( rFilter
, pControlInfo
->maFragmentPath
, aControl
) ) )
1133 // create and return the control shape (including control model)
1134 sal_Int32 nCtrlIndex
= -1;
1135 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertXControlShape( aControl
, rxShapes
, rShapeRect
, nCtrlIndex
);
1136 // on error, proceed and try to create picture from replacement image
1143 // host application wants to create the shape (do not try failed OLE controls again)
1144 if( (nShapeType
== VML_SHAPETYPE_HOSTCONTROL
) && !pControlInfo
)
1146 OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
1147 Reference
< XShape
> xShape
= mrDrawing
.createAndInsertClientXShape( *this, rxShapes
, rShapeRect
);
1152 // try to create a picture object
1153 if( !aGraphicPath
.isEmpty() )
1155 Reference
< XShape
> xShape
= SimpleShape::createPictureObject(rxShapes
, rShapeRect
, aGraphicPath
);
1156 // AS_CHARACTER shape: vertical orientation default is bottom, MSO default is top.
1157 if ( maTypeModel
.maPosition
!= "absolute" && maTypeModel
.maPosition
!= "relative" )
1158 PropertySet( xShape
).setAnyProperty( PROP_VertOrient
, makeAny(text::VertOrientation::TOP
));
1161 // default: try to create a custom shape
1162 return CustomShape::implConvertAndInsert( rxShapes
, rShapeRect
);
1165 GroupShape::GroupShape( Drawing
& rDrawing
) :
1166 ShapeBase( rDrawing
),
1167 mxChildren( new ShapeContainer( rDrawing
) )
1171 GroupShape::~GroupShape()
1175 void GroupShape::finalizeFragmentImport()
1177 // basic shape processing
1178 ShapeBase::finalizeFragmentImport();
1179 // finalize all child shapes
1180 mxChildren
->finalizeFragmentImport();
1183 const ShapeType
* GroupShape::getChildTypeById( const OUString
& rShapeId
) const
1185 return mxChildren
->getShapeTypeById( rShapeId
, true );
1188 const ShapeBase
* GroupShape::getChildById( const OUString
& rShapeId
) const
1190 return mxChildren
->getShapeById( rShapeId
, true );
1193 Reference
< XShape
> GroupShape::implConvertAndInsert( const Reference
< XShapes
>& rxShapes
, const awt::Rectangle
& rShapeRect
) const
1195 Reference
< XShape
> xGroupShape
;
1196 // check that this shape contains children and a valid coordinate system
1197 ShapeParentAnchor aParentAnchor
;
1198 aParentAnchor
.maShapeRect
= rShapeRect
;
1199 aParentAnchor
.maCoordSys
= getCoordSystem();
1200 if( !mxChildren
->empty() && (aParentAnchor
.maCoordSys
.Width
> 0) && (aParentAnchor
.maCoordSys
.Height
> 0) ) try
1202 xGroupShape
= mrDrawing
.createAndInsertXShape( "com.sun.star.drawing.GroupShape", rxShapes
, rShapeRect
);
1203 Reference
< XShapes
> xChildShapes( xGroupShape
, UNO_QUERY_THROW
);
1204 mxChildren
->convertAndInsert( xChildShapes
, &aParentAnchor
);
1205 if( !xChildShapes
->hasElements() )
1207 SAL_WARN("oox", "no child shape has been created - deleting the group shape");
1208 rxShapes
->remove( xGroupShape
);
1209 xGroupShape
.clear();
1216 if (!maTypeModel
.maEditAs
.isEmpty())
1218 uno::Reference
<beans::XPropertySet
> xPropertySet(xGroupShape
, uno::UNO_QUERY
);
1219 uno::Sequence
<beans::PropertyValue
> aGrabBag
;
1220 xPropertySet
->getPropertyValue("InteropGrabBag") >>= aGrabBag
;
1221 beans::PropertyValue aPair
;
1222 aPair
.Name
= "mso-edit-as";
1223 aPair
.Value
= uno::makeAny(maTypeModel
.maEditAs
);
1224 if (aGrabBag
.hasElements())
1226 sal_Int32 nLength
= aGrabBag
.getLength();
1227 aGrabBag
.realloc(nLength
+ 1);
1228 aGrabBag
[nLength
] = aPair
;
1232 aGrabBag
.realloc(1);
1233 aGrabBag
[0] = aPair
;
1235 xPropertySet
->setPropertyValue("InteropGrabBag", uno::makeAny(aGrabBag
));
1237 // Make sure group shapes are inline as well, unless there is an explicit different style.
1238 PropertySet
aPropertySet(xGroupShape
);
1239 const GraphicHelper
& rGraphicHelper
= mrDrawing
.getFilter().getGraphicHelper();
1240 lcl_SetAnchorType(aPropertySet
, maTypeModel
, rGraphicHelper
);
1241 if (!maTypeModel
.maRotation
.isEmpty())
1242 lcl_SetRotation(aPropertySet
, maTypeModel
.maRotation
.toInt32());
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */