fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / oox / source / vml / vmlshape.cxx
blobaa07015d68c6e11a8cb075ea895079906150d549
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <algorithm>
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;
71 namespace oox {
72 namespace vml {
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;
82 namespace {
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;
91 awt::Point aAbsPoint;
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 );
94 return aAbsPoint;
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 );
106 return aAbsRect;
109 } // namespace
111 ShapeTypeModel::ShapeTypeModel():
112 mbAutoHeight( false ),
113 mbVisible( true )
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 ) :
164 getAbsRectangle();
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 );
172 if ( nWidth == 0 )
173 nWidth = 1;
175 sal_Int32 nHeight = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true );
176 if ( nHeight == 0 )
177 nHeight = 1;
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")
182 nLeft = 1;
184 return awt::Rectangle(
185 nLeft,
186 ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginTop, 0, false, true ),
187 nWidth, nHeight );
190 awt::Rectangle ShapeType::getRelRectangle() const
192 sal_Int32 nWidth = maTypeModel.maWidth.toInt32();
193 if ( nWidth == 0 )
194 nWidth = 1;
196 sal_Int32 nHeight = maTypeModel.maHeight.toInt32();
197 if ( nHeight == 0 )
198 nHeight = 1;
200 return awt::Rectangle(
201 maTypeModel.maLeft.toInt32(),
202 maTypeModel.maTop.toInt32(),
203 nWidth, nHeight );
206 ClientData::ClientData() :
207 mnObjType( XML_TOKEN_INVALID ),
208 mnTextHAlign( XML_Left ),
209 mnTextVAlign( XML_Top ),
210 mnCol( -1 ),
211 mnRow( -1 ),
212 mnChecked( VML_CLIENTDATA_UNCHECKED ),
213 mnDropStyle( XML_Combo ),
214 mnDropLines( 1 ),
215 mnVal( 0 ),
216 mnMin( 0 ),
217 mnMax( 0 ),
218 mnInc( 0 ),
219 mnPage( 0 ),
220 mnSelType( XML_Single ),
221 mnVTEdit( VML_CLIENTDATA_TEXT ),
222 mbPrintObject( true ),
223 mbVisible( false ),
224 mbDde( false ),
225 mbNo3D( false ),
226 mbNo3D2( false ),
227 mbMultiLine( false ),
228 mbVScroll( false ),
229 mbSecretEdit( false )
233 ShapeModel::ShapeModel()
237 ShapeModel::~ShapeModel()
241 TextBox& ShapeModel::createTextBox(ShapeTypeModel& rModel)
243 mxTextBox.reset( new TextBox(rModel) );
244 return *mxTextBox;
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() );
279 if( nShapeIdx > 0 )
280 return OUStringBuffer( aBaseName ).append( ' ' ).append( nShapeIdx ).makeStringAndClear();
283 return OUString();
286 const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
288 return 0;
291 const ShapeBase* ShapeBase::getChildById( const OUString& ) const
293 return 0;
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 );
308 if( xShape.is() )
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;
317 sal_Int32 id = 0;
318 sal_Int32 idPos = sLinkChainName.indexOf("_x");
319 sal_Int32 seq = 0;
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;
328 if( getTextBox() )
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;
338 sal_Int32 length;
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)));
385 else
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;
392 sal_Int32 length;
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 );
436 else
437 SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
439 return xShape;
442 void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const
444 if( rxShape.is() )
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 );
470 return aShapeRect;
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>();
511 if (oLineWidth)
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.
537 aWrapType.clear();
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);
605 else
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")
639 bFlipX = true;
641 else if (maTypeModel.maFlip == "y")
643 bFlipY = true;
647 Reference< XShape > xShape = mrDrawing.createAndInsertXShape( maService, rxShapes, aShapeRect );
648 SdrObject* pShape = GetSdrObjectFromXShape( xShape );
649 if( pShape && getShapeType() >= 0 )
651 OUString aShapeType;
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;
713 else
715 aGrabBag.realloc(1);
716 aGrabBag[0] = aPair;
718 xPropertySet->setPropertyValue("FrameInteropGrabBag", uno::makeAny(aGrabBag));
721 else
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
735 if ( nWidth )
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
746 if ( nHeight )
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));
759 if (getTextBox())
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 );
778 if( xInStrm.is() )
779 PropertySet( xShape ).setProperty( PROP_LegacyFragment, xInStrm );
782 PropertySet aPropertySet(xShape);
783 if (xShape.is())
785 if (oRotation)
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;
804 if (bFlipX)
806 aPropSequence [nPropertyIndex].Name = "MirroredX";
807 aPropSequence [nPropertyIndex].Value = makeAny (bFlipX);
808 nPropertyIndex++;
810 if (bFlipY)
812 aPropSequence [nPropertyIndex].Name = "MirroredY";
813 aPropSequence [nPropertyIndex].Value = makeAny (bFlipY);
814 nPropertyIndex++;
816 aPropertySet.setAnyProperty(PROP_CustomShapeGeometry, makeAny( aPropSequence ) );
820 lcl_SetAnchorType(aPropertySet, maTypeModel, rGraphicHelper);
822 return xShape;
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 );
828 if( xShape.is() )
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);
852 return xShape;
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 ) );
884 return xShape;
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 );
900 // polygon path
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 );
912 return xShape;
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);
928 nIndex = 0;
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;
931 return aShapeRect;
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();
941 nIndex = 0;
942 aShapeRect.Width = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.X;
943 aShapeRect.Height = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.Y;
944 return aShapeRect;
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 >() );
981 // Start point
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 ) ) );
985 // Control point 1
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 ) ) );
989 // Control point 2
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 ) ) );
993 // End point
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
1004 else
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 ) );
1044 return xShape;
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 );
1064 catch( Exception& )
1067 return 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 ) )
1084 SAL_WARN_IF(
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 );
1097 if( xShape.is() )
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);
1108 if (xGraphic.is())
1109 aOleProps.setProperty( PROP_Graphic, xGraphic);
1112 PropertySet aPropSet( xShape );
1113 aPropSet.setProperties( aOleProps );
1115 return xShape;
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
1137 if( xShape.is() )
1138 return xShape;
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 );
1148 if( xShape.is() )
1149 return xShape;
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));
1159 return xShape;
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();
1212 catch( Exception& )
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;
1230 else
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());
1243 return xGroupShape;
1246 } // namespace vml
1247 } // namespace oox
1249 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */