Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <algorithm>
21 : #include <boost/optional.hpp>
22 :
23 : #include "oox/vml/vmlshape.hxx"
24 : #include <vcl/wmf.hxx>
25 :
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>
64 :
65 : using ::com::sun::star::beans::XPropertySet;
66 : using ::com::sun::star::uno::Any;
67 :
68 : using namespace ::com::sun::star;
69 : using namespace ::com::sun::star::text;
70 :
71 : namespace oox {
72 : namespace vml {
73 :
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;
79 :
80 : using ::oox::core::XmlFilterBase;
81 :
82 : namespace {
83 :
84 : const sal_Int32 VML_SHAPETYPE_PICTUREFRAME = 75;
85 : const sal_Int32 VML_SHAPETYPE_HOSTCONTROL = 201;
86 :
87 15674 : awt::Point lclGetAbsPoint( const awt::Point& rRelPoint, const awt::Rectangle& rShapeRect, const awt::Rectangle& rCoordSys )
88 : {
89 15674 : double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
90 15674 : double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
91 15674 : awt::Point aAbsPoint;
92 15674 : aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 );
93 15674 : aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 );
94 15674 : return aAbsPoint;
95 : }
96 :
97 600 : awt::Rectangle lclGetAbsRect( const awt::Rectangle& rRelRect, const awt::Rectangle& rShapeRect, const awt::Rectangle& rCoordSys )
98 : {
99 600 : double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
100 600 : double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
101 600 : awt::Rectangle aAbsRect;
102 600 : aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 );
103 600 : aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 );
104 600 : aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 );
105 600 : aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 );
106 600 : return aAbsRect;
107 : }
108 :
109 : } // namespace
110 :
111 1168 : ShapeTypeModel::ShapeTypeModel():
112 : mbAutoHeight( false ),
113 1168 : mbVisible( true )
114 : {
115 1168 : }
116 :
117 307 : void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource )
118 : {
119 307 : moShapeType.assignIfUsed( rSource.moShapeType );
120 307 : moCoordPos.assignIfUsed( rSource.moCoordPos );
121 307 : 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 307 : maStrokeModel.assignUsed( rSource.maStrokeModel );
125 307 : maFillModel.assignUsed( rSource.maFillModel );
126 307 : moGraphicPath.assignIfUsed( rSource.moGraphicPath );
127 307 : moGraphicTitle.assignIfUsed( rSource.moGraphicTitle );
128 307 : }
129 :
130 1168 : ShapeType::ShapeType( Drawing& rDrawing ) :
131 1168 : mrDrawing( rDrawing )
132 : {
133 1168 : }
134 :
135 1369 : ShapeType::~ShapeType()
136 : {
137 1369 : }
138 :
139 1857 : sal_Int32 ShapeType::getShapeType() const
140 : {
141 1857 : return maTypeModel.moShapeType.get( 0 );
142 : }
143 :
144 583 : OUString ShapeType::getGraphicPath() const
145 : {
146 583 : return maTypeModel.moGraphicPath.get( OUString() );
147 : }
148 :
149 377 : awt::Rectangle ShapeType::getCoordSystem() const
150 : {
151 377 : Int32Pair aCoordPos = maTypeModel.moCoordPos.get( Int32Pair( 0, 0 ) );
152 377 : Int32Pair aCoordSize = maTypeModel.moCoordSize.get( Int32Pair( 1000, 1000 ) );
153 377 : if( aCoordSize.first == 0 )
154 0 : aCoordSize.first = 1;
155 377 : if( aCoordSize.second == 0 )
156 0 : aCoordSize.second = 1;
157 377 : return awt::Rectangle( aCoordPos.first, aCoordPos.second, aCoordSize.first, aCoordSize.second );
158 : }
159 :
160 964 : awt::Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const
161 : {
162 : return pParentAnchor ?
163 2164 : lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) :
164 2892 : getAbsRectangle();
165 : }
166 :
167 362 : awt::Rectangle ShapeType::getAbsRectangle() const
168 : {
169 362 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
170 :
171 362 : sal_Int32 nWidth = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maWidth, 0, true, true );
172 362 : if ( nWidth == 0 )
173 12 : nWidth = 1;
174 :
175 362 : sal_Int32 nHeight = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true );
176 362 : if ( nHeight == 0 )
177 3 : nHeight = 1;
178 :
179 362 : sal_Int32 nLeft = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maLeft, 0, true, true )
180 362 : + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true );
181 362 : if (nLeft == 0 && maTypeModel.maPosition == "absolute")
182 57 : nLeft = 1;
183 :
184 : return awt::Rectangle(
185 : nLeft,
186 362 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginTop, 0, false, true ),
187 362 : nWidth, nHeight );
188 : }
189 :
190 597 : awt::Rectangle ShapeType::getRelRectangle() const
191 : {
192 597 : sal_Int32 nWidth = maTypeModel.maWidth.toInt32();
193 597 : if ( nWidth == 0 )
194 0 : nWidth = 1;
195 :
196 597 : sal_Int32 nHeight = maTypeModel.maHeight.toInt32();
197 597 : if ( nHeight == 0 )
198 0 : nHeight = 1;
199 :
200 : return awt::Rectangle(
201 597 : maTypeModel.maLeft.toInt32(),
202 597 : maTypeModel.maTop.toInt32(),
203 1194 : nWidth, nHeight );
204 : }
205 :
206 3 : 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 3 : mbSecretEdit( false )
230 : {
231 3 : }
232 :
233 967 : ShapeModel::ShapeModel()
234 : {
235 967 : }
236 :
237 967 : ShapeModel::~ShapeModel()
238 : {
239 967 : }
240 :
241 262 : TextBox& ShapeModel::createTextBox(ShapeTypeModel& rModel)
242 : {
243 262 : mxTextBox.reset( new TextBox(rModel) );
244 262 : return *mxTextBox;
245 : }
246 :
247 3 : ClientData& ShapeModel::createClientData()
248 : {
249 3 : mxClientData.reset( new ClientData );
250 3 : return *mxClientData;
251 : }
252 :
253 967 : ShapeBase::ShapeBase( Drawing& rDrawing ) :
254 967 : ShapeType( rDrawing )
255 : {
256 967 : }
257 :
258 967 : void ShapeBase::finalizeFragmentImport()
259 : {
260 967 : if( maShapeModel.maType.getLength() > 1 )
261 : {
262 328 : OUString aType = maShapeModel.maType;
263 328 : if (aType[ 0 ] == '#')
264 317 : aType = aType.copy(1);
265 328 : if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( aType, true ) )
266 307 : maTypeModel.assignUsed( pShapeType->getTypeModel() );
267 : }
268 967 : }
269 :
270 888 : OUString ShapeBase::getShapeName() const
271 : {
272 888 : if( !maTypeModel.maShapeName.isEmpty() )
273 345 : return maTypeModel.maShapeName;
274 :
275 543 : OUString aBaseName = mrDrawing.getShapeBaseName( *this );
276 543 : if( !aBaseName.isEmpty() )
277 : {
278 1 : sal_Int32 nShapeIdx = mrDrawing.getLocalShapeIndex( getShapeId() );
279 1 : if( nShapeIdx > 0 )
280 1 : return OUStringBuffer( aBaseName ).append( ' ' ).append( nShapeIdx ).makeStringAndClear();
281 : }
282 :
283 542 : return OUString();
284 : }
285 :
286 28 : const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
287 : {
288 28 : return 0;
289 : }
290 :
291 0 : const ShapeBase* ShapeBase::getChildById( const OUString& ) const
292 : {
293 0 : return 0;
294 : }
295 :
296 967 : Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const
297 : {
298 967 : Reference< XShape > xShape;
299 967 : if( mrDrawing.isShapeSupported( *this ) )
300 : {
301 : /* Calculate shape rectangle. Applications may do something special
302 : according to some imported shape client data (e.g. Excel cell anchor). */
303 965 : awt::Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
304 :
305 965 : if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() )
306 : {
307 965 : xShape = implConvertAndInsert( rxShapes, aShapeRect );
308 965 : if( xShape.is() )
309 : {
310 : // set imported or generated shape name (not supported by form controls)
311 963 : PropertySet aShapeProp( xShape );
312 963 : if( aShapeProp.hasProperty( PROP_Name ) )
313 887 : aShapeProp.setProperty( PROP_Name, getShapeName() );
314 1926 : uno::Reference< lang::XServiceInfo > xSInfo( xShape, uno::UNO_QUERY_THROW );
315 963 : if (xSInfo->supportsService("com.sun.star.text.TextFrame"))
316 : {
317 75 : uno::Sequence<beans::PropertyValue> aGrabBag;
318 150 : uno::Reference<beans::XPropertySet> propertySet (xShape, uno::UNO_QUERY);
319 75 : propertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
320 75 : sal_Int32 length = aGrabBag.getLength();
321 :
322 75 : aGrabBag.realloc( length+1 );
323 75 : aGrabBag[length].Name = "VML-Z-ORDER";
324 75 : aGrabBag[length].Value = uno::makeAny( maTypeModel.maZIndex.toInt32() );
325 75 : if(!(maTypeModel.maRotation).isEmpty())
326 : {
327 3 : aGrabBag.realloc( length+2 );
328 3 : aGrabBag[length+1].Name = "mso-rotation-angle";
329 3 : aGrabBag[length+1].Value = uno::makeAny(sal_Int32(NormAngle360((maTypeModel.maRotation.toInt32()) * -100)));
330 : }
331 75 : propertySet->setPropertyValue( "FrameInteropGrabBag", uno::makeAny(aGrabBag) );
332 75 : sal_Int32 backColorTransparency = 0;
333 75 : propertySet->getPropertyValue("BackColorTransparency")
334 75 : >>= backColorTransparency;
335 113 : if (propertySet->getPropertyValue("FillStyle") == FillStyle_NONE &&
336 38 : backColorTransparency == 100)
337 : {
338 : // If there is no fill, the Word default is 100% transparency.
339 38 : propertySet->setPropertyValue("FillTransparence", makeAny(sal_Int16(100)));
340 75 : }
341 : }
342 : else
343 : {
344 888 : if( maTypeModel.maZIndex.toInt32() )
345 : {
346 77 : uno::Sequence<beans::PropertyValue> aGrabBag;
347 154 : uno::Reference<beans::XPropertySet> propertySet (xShape, uno::UNO_QUERY);
348 77 : propertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
349 77 : sal_Int32 length = aGrabBag.getLength();
350 77 : aGrabBag.realloc( length+1 );
351 77 : aGrabBag[length].Name = "VML-Z-ORDER";
352 77 : aGrabBag[length].Value = uno::makeAny( maTypeModel.maZIndex.toInt32() );
353 154 : propertySet->setPropertyValue( "InteropGrabBag", uno::makeAny(aGrabBag) );
354 : }
355 : }
356 1926 : Reference< XControlShape > xControlShape( xShape, uno::UNO_QUERY );
357 963 : if ( xControlShape.is() && !getTypeModel().mbVisible )
358 : {
359 0 : PropertySet aControlShapeProp( xControlShape->getControl() );
360 0 : aControlShapeProp.setProperty( PROP_EnableVisible, uno::makeAny( sal_False ) );
361 : }
362 : /* Notify the drawing that a new shape has been inserted. For
363 : convenience, pass the rectangle that contains position and
364 : size of the shape. */
365 963 : bool bGroupChild = pParentAnchor != 0;
366 1926 : mrDrawing.notifyXShapeInserted( xShape, aShapeRect, *this, bGroupChild );
367 : }
368 : }
369 : else
370 : SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
371 : }
372 967 : return xShape;
373 : }
374 :
375 2 : void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const
376 : {
377 2 : if( rxShape.is() )
378 : {
379 : /* Calculate shape rectangle. Applications may do something special
380 : according to some imported shape client data (e.g. Excel cell anchor). */
381 2 : awt::Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
382 :
383 : // convert the shape, if the calculated rectangle is not empty
384 2 : if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) )
385 : {
386 2 : rxShape->setPosition( awt::Point( aShapeRect.X, aShapeRect.Y ) );
387 2 : rxShape->setSize( awt::Size( aShapeRect.Width, aShapeRect.Height ) );
388 2 : convertShapeProperties( rxShape );
389 : }
390 : }
391 2 : }
392 :
393 : // protected ------------------------------------------------------------------
394 :
395 967 : awt::Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor ) const
396 : {
397 : /* Calculate shape rectangle. Applications may do something special
398 : according to some imported shape client data (e.g. Excel cell anchor). */
399 967 : awt::Rectangle aShapeRect;
400 967 : const ClientData* pClientData = getClientData();
401 967 : if( !pClientData || !mrDrawing.convertClientAnchor( aShapeRect, pClientData->maAnchor ) )
402 964 : aShapeRect = getRectangle( pParentAnchor );
403 967 : return aShapeRect;
404 : }
405 :
406 897 : void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const
407 : {
408 897 : ::oox::drawingml::ShapePropertyMap aPropMap( mrDrawing.getFilter().getModelObjectHelper() );
409 897 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
410 897 : maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rGraphicHelper );
411 897 : maTypeModel.maFillModel.pushToPropMap( aPropMap, rGraphicHelper );
412 :
413 1794 : uno::Reference<lang::XServiceInfo> xSInfo(rxShape, uno::UNO_QUERY_THROW);
414 897 : if (xSInfo->supportsService("com.sun.star.text.TextFrame"))
415 : {
416 : // Any other service supporting the ShadowFormat property?
417 75 : maTypeModel.maShadowModel.pushToPropMap(aPropMap, rGraphicHelper);
418 : // TextFrames have BackColor, not FillColor
419 75 : if (aPropMap.hasProperty(PROP_FillColor))
420 : {
421 31 : aPropMap.setAnyProperty(PROP_BackColor, aPropMap.getProperty(PROP_FillColor));
422 31 : aPropMap.erase(PROP_FillColor);
423 : }
424 : // TextFrames have BackColorTransparency, not FillTransparence
425 75 : if (aPropMap.hasProperty(PROP_FillTransparence))
426 : {
427 0 : aPropMap.setAnyProperty(PROP_BackColorTransparency, aPropMap.getProperty(PROP_FillTransparence));
428 0 : aPropMap.erase(PROP_FillTransparence);
429 : }
430 : // And no LineColor property; individual borders can have colors and widths
431 75 : boost::optional<sal_Int32> oLineWidth;
432 75 : if (maTypeModel.maStrokeModel.moWeight.has())
433 16 : oLineWidth.reset(ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maStrokeModel.moWeight.get(), 0, false, false));
434 75 : if (aPropMap.hasProperty(PROP_LineColor))
435 : {
436 27 : uno::Reference<beans::XPropertySet> xPropertySet(rxShape, uno::UNO_QUERY);
437 : static const sal_Int32 aBorders[] = {
438 : PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder
439 : };
440 135 : for (unsigned int i = 0; i < SAL_N_ELEMENTS(aBorders); ++i)
441 : {
442 108 : table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(aBorders[i])).get<table::BorderLine2>();
443 108 : aBorderLine.Color = aPropMap.getProperty(PROP_LineColor).get<sal_Int32>();
444 108 : if (oLineWidth)
445 44 : aBorderLine.LineWidth = *oLineWidth;
446 108 : aPropMap.setProperty(aBorders[i], uno::makeAny(aBorderLine));
447 : }
448 27 : aPropMap.erase(PROP_LineColor);
449 75 : }
450 : }
451 822 : else if (xSInfo->supportsService("com.sun.star.drawing.CustomShape"))
452 250 : maTypeModel.maTextpathModel.pushToPropMap(aPropMap, rxShape);
453 :
454 1794 : PropertySet( rxShape ).setProperties( aPropMap );
455 897 : }
456 :
457 933 : SimpleShape::SimpleShape( Drawing& rDrawing, const OUString& rService ) :
458 : ShapeBase( rDrawing ),
459 933 : maService( rService )
460 : {
461 933 : }
462 :
463 962 : void lcl_setSurround(PropertySet& rPropSet, const ShapeTypeModel& rTypeModel)
464 : {
465 962 : sal_Int32 nSurround = com::sun::star::text::WrapTextMode_THROUGHT;
466 1918 : if ( rTypeModel.moWrapType.get() == "square" || rTypeModel.moWrapType .get()== "tight" ||
467 956 : rTypeModel.moWrapType.get() == "through" )
468 : {
469 6 : nSurround = com::sun::star::text::WrapTextMode_PARALLEL;
470 6 : if ( rTypeModel.moWrapSide.get() == "left" )
471 0 : nSurround = com::sun::star::text::WrapTextMode_LEFT;
472 6 : else if ( rTypeModel.moWrapSide.get() == "right" )
473 0 : nSurround = com::sun::star::text::WrapTextMode_RIGHT;
474 : }
475 956 : else if ( rTypeModel.moWrapType.get() == "topAndBottom" )
476 0 : nSurround = com::sun::star::text::WrapTextMode_NONE;
477 :
478 962 : rPropSet.setProperty(PROP_Surround, nSurround);
479 962 : }
480 :
481 962 : void lcl_SetAnchorType(PropertySet& rPropSet, const ShapeTypeModel& rTypeModel)
482 : {
483 962 : if ( rTypeModel.maPositionHorizontal == "center" )
484 47 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::CENTER));
485 915 : else if ( rTypeModel.maPositionHorizontal == "left" )
486 2 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::LEFT));
487 913 : else if ( rTypeModel.maPositionHorizontal == "right" )
488 4 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::RIGHT));
489 909 : else if ( rTypeModel.maPositionHorizontal == "inside" )
490 : {
491 0 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::LEFT));
492 0 : rPropSet.setAnyProperty(PROP_PageToggle, makeAny(sal_True));
493 : }
494 909 : else if ( rTypeModel.maPositionHorizontal == "outside" )
495 : {
496 0 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::RIGHT));
497 0 : rPropSet.setAnyProperty(PROP_PageToggle, makeAny(sal_True));
498 : }
499 :
500 962 : if ( rTypeModel.maPositionHorizontalRelative == "page" )
501 44 : rPropSet.setAnyProperty(PROP_HoriOrientRelation, makeAny(text::RelOrientation::PAGE_FRAME));
502 918 : else if ( rTypeModel.maPositionVerticalRelative == "margin" )
503 41 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::PAGE_PRINT_AREA);
504 877 : else if ( rTypeModel.maPositionVerticalRelative == "text" )
505 17 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::FRAME);
506 :
507 962 : if ( rTypeModel.maPositionVertical == "center" )
508 39 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::CENTER));
509 923 : else if ( rTypeModel.maPositionVertical == "top" )
510 9 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::TOP));
511 914 : else if ( rTypeModel.maPositionVertical == "bottom" )
512 0 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::BOTTOM));
513 914 : else if ( rTypeModel.maPositionVertical == "inside" )
514 0 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::LINE_TOP));
515 914 : else if ( rTypeModel.maPositionVertical == "outside" )
516 0 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::LINE_BOTTOM));
517 :
518 962 : if ( rTypeModel.maPosition == "absolute" )
519 : {
520 : // Word supports as-character (inline) and at-character only, absolute can't be inline.
521 772 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AT_CHARACTER);
522 :
523 772 : if ( rTypeModel.maPositionVerticalRelative == "page" )
524 : {
525 39 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::PAGE_FRAME);
526 : }
527 733 : else if ( rTypeModel.maPositionVerticalRelative == "margin" )
528 : {
529 42 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::PAGE_PRINT_AREA);
530 : }
531 : else
532 : {
533 691 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::FRAME);
534 : }
535 : }
536 190 : else if( rTypeModel.maPosition == "relative" )
537 : { // I'm not very sure this is correct either.
538 0 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AT_PARAGRAPH);
539 : }
540 : else // static (is the default) means anchored inline
541 : {
542 190 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AS_CHARACTER);
543 : }
544 962 : lcl_setSurround( rPropSet, rTypeModel );
545 962 : }
546 :
547 43 : void lcl_SetRotation(PropertySet& rPropSet, const sal_Int32 nRotation)
548 : {
549 : // See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation angles are clockwise, we have them as counter-clockwise.
550 : // Additionally, VML type is 0..360, our is 0..36000.
551 43 : rPropSet.setAnyProperty(PROP_RotateAngle, makeAny(sal_Int32(NormAngle360(nRotation * -100))));
552 43 : }
553 :
554 770 : Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
555 : {
556 770 : awt::Rectangle aShapeRect(rShapeRect);
557 770 : boost::optional<sal_Int32> oRotation;
558 770 : bool bFlipX = false, bFlipY = false;
559 770 : if (!maTypeModel.maRotation.isEmpty())
560 42 : oRotation.reset(maTypeModel.maRotation.toInt32());
561 770 : if (!maTypeModel.maFlip.isEmpty())
562 : {
563 17 : if (maTypeModel.maFlip == "x")
564 : {
565 7 : bFlipX = true;
566 : }
567 10 : else if (maTypeModel.maFlip == "y")
568 : {
569 7 : bFlipY = true;
570 : }
571 : }
572 :
573 770 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( maService, rxShapes, aShapeRect );
574 770 : SdrObject* pShape = GetSdrObjectFromXShape( xShape );
575 770 : if( pShape && getShapeType() >= 0 )
576 : {
577 693 : OUString aShapeType;
578 693 : aShapeType = EnhancedCustomShapeTypeNames::Get( static_cast< MSO_SPT >(getShapeType()) );
579 : //The resize autoshape to fit text attr of FontWork/Word-Art should always be false
580 : //for the fallback geometry.
581 693 : if(aShapeType.startsWith("fontwork"))
582 : {
583 34 : pShape->SetMergedItem(makeSdrTextAutoGrowHeightItem(false));
584 34 : pShape->SetMergedItem(makeSdrTextAutoGrowWidthItem(false));
585 693 : }
586 : }
587 770 : convertShapeProperties( xShape );
588 :
589 : // Handle left/right/top/bottom wrap distance.
590 : // Default value of mso-wrap-distance-left/right is supposed to be 0 (see
591 : // 19.1.2.19 of the VML spec), but Word implements a non-zero value.
592 : // [MS-ODRAW] says the below default value in 2.3.4.9.
593 770 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
594 1540 : OUString aWrapDistanceLeft = OUString::number(0x0001BE7C);
595 770 : if (!maTypeModel.maWrapDistanceLeft.isEmpty())
596 4 : aWrapDistanceLeft = maTypeModel.maWrapDistanceLeft;
597 770 : sal_Int32 nWrapDistanceLeft = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, aWrapDistanceLeft, 0, true, false);
598 770 : PropertySet(xShape).setAnyProperty(PROP_LeftMargin, uno::makeAny(nWrapDistanceLeft));
599 1540 : OUString aWrapDistanceRight = OUString::number(0x0001BE7C);
600 770 : if (!maTypeModel.maWrapDistanceRight.isEmpty())
601 4 : aWrapDistanceRight = maTypeModel.maWrapDistanceRight;
602 770 : sal_Int32 nWrapDistanceRight = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, aWrapDistanceRight, 0, true, false);
603 770 : PropertySet(xShape).setAnyProperty(PROP_RightMargin, uno::makeAny(nWrapDistanceRight));
604 770 : sal_Int32 nWrapDistanceTop = 0;
605 770 : if (!maTypeModel.maWrapDistanceTop.isEmpty())
606 6 : nWrapDistanceTop = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceTop, 0, false, true);
607 770 : PropertySet(xShape).setAnyProperty(PROP_TopMargin, uno::makeAny(nWrapDistanceTop));
608 770 : sal_Int32 nWrapDistanceBottom = 0;
609 770 : if (!maTypeModel.maWrapDistanceBottom.isEmpty())
610 6 : nWrapDistanceBottom = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maWrapDistanceBottom, 0, false, true);
611 770 : PropertySet(xShape).setAnyProperty(PROP_BottomMargin, uno::makeAny(nWrapDistanceBottom));
612 :
613 770 : if ( maService == "com.sun.star.text.TextFrame" )
614 : {
615 75 : PropertySet( xShape ).setAnyProperty( PROP_FrameIsAutomaticHeight, makeAny( maTypeModel.mbAutoHeight ) );
616 75 : PropertySet( xShape ).setAnyProperty( PROP_SizeType, makeAny( maTypeModel.mbAutoHeight ? SizeType::MIN : SizeType::FIX ) );
617 75 : if( getTextBox()->borderDistanceSet )
618 : {
619 75 : PropertySet( xShape ).setAnyProperty( PROP_LeftBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceLeft )));
620 75 : PropertySet( xShape ).setAnyProperty( PROP_TopBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceTop )));
621 75 : PropertySet( xShape ).setAnyProperty( PROP_RightBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceRight )));
622 75 : PropertySet( xShape ).setAnyProperty( PROP_BottomBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceBottom )));
623 : }
624 75 : if (!maTypeModel.maLayoutFlowAlt.isEmpty())
625 : {
626 : // Can't handle this property here, as the frame is not attached yet: pass it to writerfilter.
627 3 : uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
628 6 : uno::Sequence<beans::PropertyValue> aGrabBag;
629 3 : xPropertySet->getPropertyValue("FrameInteropGrabBag") >>= aGrabBag;
630 6 : beans::PropertyValue aPair;
631 3 : aPair.Name = "mso-layout-flow-alt";
632 3 : aPair.Value = uno::makeAny(maTypeModel.maLayoutFlowAlt);
633 3 : if (aGrabBag.hasElements())
634 : {
635 0 : sal_Int32 nLength = aGrabBag.getLength();
636 0 : aGrabBag.realloc(nLength + 1);
637 0 : aGrabBag[nLength] = aPair;
638 : }
639 : else
640 : {
641 3 : aGrabBag.realloc(1);
642 3 : aGrabBag[0] = aPair;
643 : }
644 6 : xPropertySet->setPropertyValue("FrameInteropGrabBag", uno::makeAny(aGrabBag));
645 : }
646 : }
647 : else
648 : {
649 : // FIXME Setting the relative width/heigh only for everything but text frames as
650 : // TextFrames already have relative width/height feature... but currently not working
651 : // in the way we need.
652 :
653 : // Set the relative width / height if any
654 695 : if ( !maTypeModel.maWidthPercent.isEmpty( ) )
655 : {
656 : // Only page-relative width is supported ATM
657 4 : if ( maTypeModel.maWidthRelative.isEmpty() || maTypeModel.maWidthRelative == "page" )
658 : {
659 2 : sal_Int16 nWidth = maTypeModel.maWidthPercent.toInt32() / 10;
660 : // Only apply if nWidth != 0
661 2 : if ( nWidth )
662 2 : PropertySet( xShape ).setAnyProperty(PROP_RelativeWidth, makeAny( nWidth ) );
663 : }
664 : }
665 695 : if ( !maTypeModel.maHeightPercent.isEmpty( ) )
666 : {
667 : // Only page-relative height is supported ATM
668 4 : if ( maTypeModel.maHeightRelative.isEmpty() || maTypeModel.maHeightRelative == "page" )
669 : {
670 4 : sal_Int16 nHeight = maTypeModel.maHeightPercent.toInt32() / 10;
671 : // Only apply if nHeight != 0
672 4 : if ( nHeight )
673 4 : PropertySet( xShape ).setAnyProperty(PROP_RelativeHeight, makeAny( nHeight ) );
674 : }
675 : }
676 :
677 : // drawinglayer default is center, MSO default is top.
678 695 : drawing::TextVerticalAdjust eTextVerticalAdjust = drawing::TextVerticalAdjust_TOP;
679 695 : if (maTypeModel.maVTextAnchor == "middle")
680 1 : eTextVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
681 694 : else if (maTypeModel.maVTextAnchor == "bottom")
682 1 : eTextVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
683 695 : PropertySet(xShape).setAnyProperty(PROP_TextVerticalAdjust, makeAny(eTextVerticalAdjust));
684 :
685 695 : if (getTextBox())
686 : {
687 182 : getTextBox()->convert(xShape);
688 182 : if (getTextBox()->borderDistanceSet)
689 : {
690 182 : awt::Size aSize = xShape->getSize();
691 182 : PropertySet(xShape).setAnyProperty(PROP_TextLeftDistance, makeAny(sal_Int32(getTextBox()->borderDistanceLeft)));
692 182 : PropertySet(xShape).setAnyProperty(PROP_TextUpperDistance, makeAny(sal_Int32(getTextBox()->borderDistanceTop)));
693 182 : PropertySet(xShape).setAnyProperty(PROP_TextRightDistance, makeAny(sal_Int32(getTextBox()->borderDistanceRight)));
694 182 : PropertySet(xShape).setAnyProperty(PROP_TextLowerDistance, makeAny(sal_Int32(getTextBox()->borderDistanceBottom)));
695 182 : xShape->setSize(aSize);
696 : }
697 : }
698 : }
699 :
700 : // Import Legacy Fragments (if any)
701 770 : if( xShape.is() && !maShapeModel.maLegacyDiagramPath.isEmpty() )
702 : {
703 0 : Reference< XInputStream > xInStrm( mrDrawing.getFilter().openInputStream( maShapeModel.maLegacyDiagramPath ), UNO_SET_THROW );
704 0 : if( xInStrm.is() )
705 0 : PropertySet( xShape ).setProperty( PROP_LegacyFragment, xInStrm );
706 : }
707 :
708 1540 : PropertySet aPropertySet(xShape);
709 770 : if (xShape.is())
710 : {
711 770 : if (oRotation)
712 : {
713 42 : lcl_SetRotation(aPropertySet, *oRotation);
714 42 : uno::Reference<lang::XServiceInfo> xServiceInfo(rxShapes, uno::UNO_QUERY);
715 42 : if (!xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
716 : {
717 : // If rotation is used, simple setPosition() is not enough.
718 33 : aPropertySet.setAnyProperty(PROP_HoriOrientPosition, makeAny(aShapeRect.X));
719 33 : aPropertySet.setAnyProperty(PROP_VertOrientPosition, makeAny(aShapeRect.Y));
720 42 : }
721 : }
722 :
723 : // When flip has 'x' or 'y', the associated ShapeRect will be changed but direction change doesn't occur.
724 : // It might occur internally in SdrObject of "sw" module, not here.
725 : // The associated properties "PROP_MirroredX" and "PROP_MirroredY" have to be set here so that direction change will occur internally.
726 770 : if (bFlipX || bFlipY)
727 : {
728 14 : com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > aPropSequence (2);
729 14 : int nPropertyIndex = 0;
730 14 : if (bFlipX)
731 : {
732 7 : aPropSequence [nPropertyIndex].Name = "MirroredX";
733 7 : aPropSequence [nPropertyIndex].Value = makeAny (bFlipX);
734 7 : nPropertyIndex++;
735 : }
736 14 : if (bFlipY)
737 : {
738 7 : aPropSequence [nPropertyIndex].Name = "MirroredY";
739 7 : aPropSequence [nPropertyIndex].Value = makeAny (bFlipY);
740 7 : nPropertyIndex++;
741 : }
742 14 : aPropertySet.setAnyProperty(PROP_CustomShapeGeometry, makeAny( aPropSequence ) );
743 : }
744 : }
745 :
746 770 : lcl_SetAnchorType(aPropertySet, maTypeModel);
747 :
748 1540 : return xShape;
749 : }
750 :
751 158 : Reference< XShape > SimpleShape::createPictureObject( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect, OUString& rGraphicPath ) const
752 : {
753 158 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.GraphicObjectShape", rxShapes, rShapeRect );
754 158 : if( xShape.is() )
755 : {
756 158 : XmlFilterBase& rFilter = mrDrawing.getFilter();
757 158 : OUString aGraphicUrl = rFilter.getGraphicHelper().importEmbeddedGraphicObject( rGraphicPath );
758 316 : PropertySet aPropSet( xShape );
759 158 : if( !aGraphicUrl.isEmpty() )
760 : {
761 158 : aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl );
762 : }
763 316 : uno::Reference< lang::XServiceInfo > xServiceInfo(rxShapes, uno::UNO_QUERY);
764 : // If the shape has an absolute position, set the properties accordingly, unless we're inside a group shape.
765 158 : if ( maTypeModel.maPosition == "absolute" && !xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
766 : {
767 31 : aPropSet.setProperty(PROP_HoriOrientPosition, rShapeRect.X);
768 31 : aPropSet.setProperty(PROP_VertOrientPosition, rShapeRect.Y);
769 31 : aPropSet.setProperty(PROP_Opaque, sal_False);
770 : }
771 : // fdo#70457: preserve rotation information
772 158 : if ( !maTypeModel.maRotation.isEmpty() )
773 0 : lcl_SetRotation( aPropSet, maTypeModel.maRotation.toInt32() );
774 :
775 316 : lcl_SetAnchorType(aPropSet, maTypeModel);
776 : }
777 158 : return xShape;
778 : }
779 :
780 237 : RectangleShape::RectangleShape( Drawing& rDrawing ) :
781 237 : SimpleShape( rDrawing, "com.sun.star.drawing.RectangleShape" )
782 : {
783 237 : }
784 :
785 237 : Reference<XShape> RectangleShape::implConvertAndInsert(const Reference<XShapes>& rxShapes, const awt::Rectangle& rShapeRect) const
786 : {
787 237 : OUString aGraphicPath = getGraphicPath();
788 :
789 : // try to create a picture object
790 237 : if(!aGraphicPath.isEmpty())
791 3 : return SimpleShape::createPictureObject(rxShapes, rShapeRect, aGraphicPath);
792 :
793 : // default: try to create a rectangle shape
794 468 : Reference<XShape> xShape = SimpleShape::implConvertAndInsert(rxShapes, rShapeRect);
795 468 : OUString sArcsize = maTypeModel.maArcsize;
796 234 : if ( !sArcsize.isEmpty( ) )
797 : {
798 3 : sal_Unicode cLastChar = sArcsize[sArcsize.getLength() - 1];
799 3 : sal_Int32 nValue = sArcsize.copy( 0, sArcsize.getLength() - 1 ).toInt32( );
800 : // Get the smallest half-side
801 3 : double size = std::min( rShapeRect.Height, rShapeRect.Width ) / 2.0;
802 3 : sal_Int32 nRadius = 0;
803 3 : if ( cLastChar == 'f' )
804 3 : nRadius = size * nValue / 65536;
805 0 : else if ( cLastChar == '%' )
806 0 : nRadius = size * nValue / 100;
807 3 : PropertySet( xShape ).setAnyProperty( PROP_CornerRadius, makeAny( nRadius ) );
808 : }
809 471 : return xShape;
810 : }
811 :
812 2 : EllipseShape::EllipseShape( Drawing& rDrawing ) :
813 2 : SimpleShape( rDrawing, "com.sun.star.drawing.EllipseShape" )
814 : {
815 2 : }
816 :
817 2 : PolyLineShape::PolyLineShape( Drawing& rDrawing ) :
818 2 : SimpleShape( rDrawing, "com.sun.star.drawing.PolyLineShape" )
819 : {
820 2 : }
821 :
822 2 : Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
823 : {
824 2 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
825 : // polygon path
826 2 : awt::Rectangle aCoordSys = getCoordSystem();
827 2 : if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
828 : {
829 2 : ::std::vector< awt::Point > aAbsPoints;
830 6 : for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt )
831 4 : aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) );
832 4 : PointSequenceSequence aPointSeq( 1 );
833 2 : aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints );
834 4 : PropertySet aPropSet( xShape );
835 4 : aPropSet.setProperty( PROP_PolyPolygon, aPointSeq );
836 : }
837 2 : return xShape;
838 : }
839 :
840 5 : LineShape::LineShape(Drawing& rDrawing)
841 5 : : SimpleShape(rDrawing, "com.sun.star.drawing.LineShape")
842 : {
843 5 : }
844 :
845 2 : awt::Rectangle LineShape::getAbsRectangle() const
846 : {
847 2 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
848 2 : awt::Rectangle aShapeRect;
849 2 : sal_Int32 nIndex = 0;
850 :
851 2 : aShapeRect.X = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maFrom.getToken(0, ',', nIndex), 0, true, true);
852 2 : aShapeRect.Y = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maFrom.getToken(0, ',', nIndex), 0, false, true);
853 2 : nIndex = 0;
854 2 : aShapeRect.Width = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maTo.getToken(0, ',', nIndex), 0, true, true) - aShapeRect.X;
855 2 : aShapeRect.Height = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maTo.getToken(0, ',', nIndex), 0, false, true) - aShapeRect.Y;
856 2 : return aShapeRect;
857 : }
858 :
859 3 : awt::Rectangle LineShape::getRelRectangle() const
860 : {
861 3 : awt::Rectangle aShapeRect;
862 3 : sal_Int32 nIndex = 0;
863 :
864 3 : aShapeRect.X = maShapeModel.maFrom.getToken(0, ',', nIndex).toInt32();
865 3 : aShapeRect.Y = maShapeModel.maFrom.getToken(0, ',', nIndex).toInt32();
866 3 : nIndex = 0;
867 3 : aShapeRect.Width = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.X;
868 3 : aShapeRect.Height = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.Y;
869 3 : return aShapeRect;
870 : }
871 :
872 341 : BezierShape::BezierShape(Drawing& rDrawing)
873 341 : : SimpleShape(rDrawing, "com.sun.star.drawing.OpenBezierShape")
874 : {
875 341 : }
876 :
877 341 : Reference< XShape > BezierShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
878 : {
879 : // If we have an 'x' in the last part of the path it means it is closed...
880 341 : sal_Int32 nPos = maShapeModel.maVmlPath.lastIndexOf(',');
881 341 : if ( nPos != -1 && maShapeModel.maVmlPath.copy(nPos).indexOf('x') != -1 )
882 : {
883 338 : const_cast<BezierShape*>( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
884 : }
885 :
886 341 : awt::Rectangle aCoordSys = getCoordSystem();
887 341 : PolyPolygonBezierCoords aBezierCoords;
888 :
889 341 : if( (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
890 : {
891 341 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
892 :
893 : // Bezier paths may consist of one or more sub-paths
894 : typedef ::std::vector< ::std::vector< awt::Point > > SubPathList;
895 : typedef ::std::vector< ::std::vector< PolygonFlags > > FlagsList;
896 341 : SubPathList aCoordLists;
897 682 : FlagsList aFlagLists;
898 341 : sal_Int32 nIndex = 0;
899 :
900 : // Curve defined by to, from, control1 and control2 attributes
901 341 : if ( maShapeModel.maVmlPath.isEmpty() )
902 : {
903 0 : aCoordLists.push_back( ::std::vector< awt::Point >() );
904 0 : aFlagLists.push_back( ::std::vector< PolygonFlags >() );
905 :
906 : // Start point
907 0 : aCoordLists[ 0 ].push_back(
908 0 : awt::Point(ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, true, true ),
909 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, false, true ) ) );
910 : // Control point 1
911 0 : aCoordLists[ 0 ].push_back(
912 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, true, true ),
913 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, false, true ) ) );
914 : // Control point 2
915 0 : aCoordLists[ 0 ].push_back(
916 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, true, true ),
917 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, false, true ) ) );
918 : // End point
919 0 : aCoordLists[ 0 ].push_back(
920 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, true, true ),
921 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, false, true ) ) );
922 :
923 : // First and last points are normals, points 2 and 4 are controls
924 0 : aFlagLists[ 0 ].resize( aCoordLists[ 0 ].size(), PolygonFlags_CONTROL );
925 0 : aFlagLists[ 0 ][ 0 ] = PolygonFlags_NORMAL;
926 0 : aFlagLists[ 0 ].back() = PolygonFlags_NORMAL;
927 : }
928 : // Curve defined by path attribute
929 : else
930 : {
931 : // Parse VML path string and convert to absolute coordinates
932 341 : ConversionHelper::decodeVmlPath( aCoordLists, aFlagLists, maShapeModel.maVmlPath );
933 :
934 889 : for ( SubPathList::iterator aListIt = aCoordLists.begin(); aListIt != aCoordLists.end(); ++aListIt )
935 16218 : for ( ::std::vector< awt::Point >::iterator aPointIt = (*aListIt).begin(); aPointIt != (*aListIt).end(); ++aPointIt)
936 : {
937 15670 : (*aPointIt) = lclGetAbsPoint( (*aPointIt), rShapeRect, aCoordSys );
938 : }
939 : }
940 :
941 341 : aBezierCoords.Coordinates.realloc( aCoordLists.size() );
942 889 : for ( size_t i = 0; i < aCoordLists.size(); i++ )
943 548 : aBezierCoords.Coordinates[i] = ContainerHelper::vectorToSequence( aCoordLists[i] );
944 :
945 341 : aBezierCoords.Flags.realloc( aFlagLists.size() );
946 889 : for ( size_t i = 0; i < aFlagLists.size(); i++ )
947 548 : aBezierCoords.Flags[i] = ContainerHelper::vectorToSequence( aFlagLists[i] );
948 :
949 1023 : if( !aCoordLists.front().empty() && !aCoordLists.back().empty()
950 341 : && aCoordLists.front().front().X == aCoordLists.back().back().X
951 603 : && aCoordLists.front().front().Y == aCoordLists.back().back().Y )
952 : { // HACK: If the shape is in fact closed, which can be found out only when the path is known,
953 : // force to closed bezier shape (otherwise e.g. fill won't work).
954 262 : const_cast< BezierShape* >( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
955 341 : }
956 : }
957 :
958 341 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
959 :
960 341 : if( aBezierCoords.Coordinates.hasElements())
961 : {
962 341 : PropertySet aPropSet( xShape );
963 341 : aPropSet.setProperty( PROP_PolyPolygonBezier, aBezierCoords );
964 : }
965 :
966 : // Hacky way of ensuring the shape is correctly sized/positioned
967 341 : xShape->setSize( awt::Size( rShapeRect.Width, rShapeRect.Height ) );
968 341 : xShape->setPosition( awt::Point( rShapeRect.X, rShapeRect.Y ) );
969 341 : return xShape;
970 : }
971 :
972 346 : CustomShape::CustomShape( Drawing& rDrawing ) :
973 346 : SimpleShape( rDrawing, "com.sun.star.drawing.CustomShape" )
974 : {
975 346 : }
976 :
977 186 : Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
978 : {
979 : // try to create a custom shape
980 186 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
981 186 : if( xShape.is() ) try
982 : {
983 : // create the custom shape geometry
984 186 : Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW );
985 125 : xDefaulter->createCustomShapeDefaults( OUString::number( getShapeType() ) );
986 : // convert common properties
987 125 : convertShapeProperties( xShape );
988 : }
989 61 : catch( Exception& )
990 : {
991 : }
992 186 : return xShape;
993 : }
994 :
995 346 : ComplexShape::ComplexShape( Drawing& rDrawing ) :
996 346 : CustomShape( rDrawing )
997 : {
998 346 : }
999 :
1000 344 : Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
1001 : {
1002 344 : XmlFilterBase& rFilter = mrDrawing.getFilter();
1003 344 : sal_Int32 nShapeType = getShapeType();
1004 344 : OUString aGraphicPath = getGraphicPath();
1005 :
1006 : // try to find registered OLE object info
1007 344 : if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) )
1008 : {
1009 : SAL_WARN_IF(
1010 : nShapeType != VML_SHAPETYPE_PICTUREFRAME, "oox",
1011 : "ComplexShape::implConvertAndInsert - unexpected shape type");
1012 :
1013 : // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
1014 2 : if( pOleObjectInfo->mbDmlShape )
1015 4 : return Reference< XShape >();
1016 :
1017 0 : PropertyMap aOleProps;
1018 0 : awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height );
1019 0 : if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) )
1020 : {
1021 0 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.OLE2Shape", rxShapes, rShapeRect );
1022 0 : if( xShape.is() )
1023 : {
1024 : // set the replacement graphic
1025 0 : if( !aGraphicPath.isEmpty() )
1026 : {
1027 0 : WMF_EXTERNALHEADER aExtHeader;
1028 0 : aExtHeader.mapMode = 8;
1029 0 : aExtHeader.xExt = rShapeRect.Width;
1030 0 : aExtHeader.yExt = rShapeRect.Height;
1031 :
1032 0 : Reference< XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic(aGraphicPath, &aExtHeader);
1033 0 : if (xGraphic.is())
1034 0 : aOleProps.setProperty( PROP_Graphic, xGraphic);
1035 : }
1036 :
1037 0 : PropertySet aPropSet( xShape );
1038 0 : aPropSet.setProperties( aOleProps );
1039 :
1040 0 : return xShape;
1041 0 : }
1042 0 : }
1043 : }
1044 :
1045 : // try to find registered form control info
1046 342 : const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId );
1047 342 : if( pControlInfo && !pControlInfo->maFragmentPath.isEmpty() )
1048 : {
1049 : OSL_ENSURE( nShapeType == VML_SHAPETYPE_HOSTCONTROL, "ComplexShape::implConvertAndInsert - unexpected shape type" );
1050 0 : OUString aShapeName = getShapeName();
1051 0 : if( !aShapeName.isEmpty() )
1052 : {
1053 : OSL_ENSURE( aShapeName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" );
1054 : // load the control properties from fragment
1055 0 : ::oox::ole::EmbeddedControl aControl( aShapeName );
1056 0 : if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) )
1057 : {
1058 : // create and return the control shape (including control model)
1059 0 : sal_Int32 nCtrlIndex = -1;
1060 0 : Reference< XShape > xShape = mrDrawing.createAndInsertXControlShape( aControl, rxShapes, rShapeRect, nCtrlIndex );
1061 : // on error, proceed and try to create picture from replacement image
1062 0 : if( xShape.is() )
1063 0 : return xShape;
1064 0 : }
1065 0 : }
1066 : }
1067 :
1068 : // host application wants to create the shape (do not try failed OLE controls again)
1069 342 : if( (nShapeType == VML_SHAPETYPE_HOSTCONTROL) && !pControlInfo )
1070 : {
1071 : OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
1072 1 : Reference< XShape > xShape = mrDrawing.createAndInsertClientXShape( *this, rxShapes, rShapeRect );
1073 1 : if( xShape.is() )
1074 1 : return xShape;
1075 : }
1076 :
1077 : // try to create a picture object
1078 341 : if( !aGraphicPath.isEmpty() )
1079 : {
1080 155 : Reference< XShape > xShape = SimpleShape::createPictureObject(rxShapes, rShapeRect, aGraphicPath);
1081 : // AS_CHARACTER shape: vertical orientation default is bottom, MSO default is top.
1082 155 : if ( maTypeModel.maPosition != "absolute" && maTypeModel.maPosition != "relative" )
1083 118 : PropertySet( xShape ).setAnyProperty( PROP_VertOrient, makeAny(text::VertOrientation::TOP));
1084 155 : return xShape;
1085 : }
1086 : // default: try to create a custom shape
1087 186 : return CustomShape::implConvertAndInsert( rxShapes, rShapeRect );
1088 : }
1089 :
1090 34 : GroupShape::GroupShape( Drawing& rDrawing ) :
1091 : ShapeBase( rDrawing ),
1092 34 : mxChildren( new ShapeContainer( rDrawing ) )
1093 : {
1094 34 : }
1095 :
1096 68 : GroupShape::~GroupShape()
1097 : {
1098 68 : }
1099 :
1100 34 : void GroupShape::finalizeFragmentImport()
1101 : {
1102 : // basic shape processing
1103 34 : ShapeBase::finalizeFragmentImport();
1104 : // finalize all child shapes
1105 34 : mxChildren->finalizeFragmentImport();
1106 34 : }
1107 :
1108 62 : const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const
1109 : {
1110 62 : return mxChildren->getShapeTypeById( rShapeId, true );
1111 : }
1112 :
1113 0 : const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const
1114 : {
1115 0 : return mxChildren->getShapeById( rShapeId, true );
1116 : }
1117 :
1118 34 : Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
1119 : {
1120 34 : Reference< XShape > xGroupShape;
1121 : // check that this shape contains children and a valid coordinate system
1122 34 : ShapeParentAnchor aParentAnchor;
1123 34 : aParentAnchor.maShapeRect = rShapeRect;
1124 34 : aParentAnchor.maCoordSys = getCoordSystem();
1125 34 : if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try
1126 : {
1127 34 : xGroupShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.GroupShape", rxShapes, rShapeRect );
1128 34 : Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
1129 34 : mxChildren->convertAndInsert( xChildShapes, &aParentAnchor );
1130 34 : if( !xChildShapes->hasElements() )
1131 : {
1132 : SAL_WARN("oox", "no child shape has been created - deleting the group shape");
1133 0 : rxShapes->remove( xGroupShape );
1134 0 : xGroupShape.clear();
1135 34 : }
1136 : }
1137 0 : catch( Exception& )
1138 : {
1139 : }
1140 :
1141 34 : if (!maTypeModel.maEditAs.isEmpty())
1142 : {
1143 14 : uno::Reference<beans::XPropertySet> xPropertySet(xGroupShape, uno::UNO_QUERY);
1144 28 : uno::Sequence<beans::PropertyValue> aGrabBag;
1145 14 : xPropertySet->getPropertyValue("InteropGrabBag") >>= aGrabBag;
1146 28 : beans::PropertyValue aPair;
1147 14 : aPair.Name = "mso-edit-as";
1148 14 : aPair.Value = uno::makeAny(maTypeModel.maEditAs);
1149 14 : if (aGrabBag.hasElements())
1150 : {
1151 0 : sal_Int32 nLength = aGrabBag.getLength();
1152 0 : aGrabBag.realloc(nLength + 1);
1153 0 : aGrabBag[nLength] = aPair;
1154 : }
1155 : else
1156 : {
1157 14 : aGrabBag.realloc(1);
1158 14 : aGrabBag[0] = aPair;
1159 : }
1160 28 : xPropertySet->setPropertyValue("InteropGrabBag", uno::makeAny(aGrabBag));
1161 : }
1162 : // Make sure group shapes are inline as well, unless there is an explicit different style.
1163 68 : PropertySet aPropertySet(xGroupShape);
1164 34 : lcl_SetAnchorType(aPropertySet, maTypeModel);
1165 34 : if (!maTypeModel.maRotation.isEmpty())
1166 1 : lcl_SetRotation(aPropertySet, maTypeModel.maRotation.toInt32());
1167 68 : return xGroupShape;
1168 : }
1169 :
1170 : } // namespace vml
1171 246 : } // namespace oox
1172 :
1173 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|