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 :
25 : #include <com/sun/star/beans/PropertyValues.hpp>
26 : #include <com/sun/star/beans/XPropertySet.hpp>
27 : #include <com/sun/star/awt/XControlModel.hpp>
28 : #include <com/sun/star/drawing/PointSequenceSequence.hpp>
29 : #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30 : #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
31 : #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
32 : #include <com/sun/star/drawing/XShapes.hpp>
33 : #include <com/sun/star/drawing/XControlShape.hpp>
34 : #include <com/sun/star/graphic/XGraphic.hpp>
35 : #include <com/sun/star/table/BorderLine2.hpp>
36 : #include <com/sun/star/text/HoriOrientation.hpp>
37 : #include <com/sun/star/text/RelOrientation.hpp>
38 : #include <com/sun/star/text/SizeType.hpp>
39 : #include <com/sun/star/text/VertOrientation.hpp>
40 : #include <com/sun/star/text/WrapTextMode.hpp>
41 : #include <com/sun/star/text/XTextContent.hpp>
42 : #include <com/sun/star/text/XTextDocument.hpp>
43 : #include <com/sun/star/text/XTextFrame.hpp>
44 : #include <com/sun/star/text/TextContentAnchorType.hpp>
45 : #include <rtl/math.hxx>
46 : #include <rtl/ustrbuf.hxx>
47 : #include <svx/svdtrans.hxx>
48 : #include "oox/drawingml/shapepropertymap.hxx"
49 : #include "oox/helper/graphichelper.hxx"
50 : #include "oox/helper/propertyset.hxx"
51 : #include "oox/ole/axcontrol.hxx"
52 : #include "oox/ole/axcontrolfragment.hxx"
53 : #include "oox/ole/oleobjecthelper.hxx"
54 : #include "oox/vml/vmldrawing.hxx"
55 : #include "oox/vml/vmlshapecontainer.hxx"
56 : #include "oox/vml/vmltextbox.hxx"
57 : #include "oox/core/xmlfilterbase.hxx"
58 : #include "oox/helper/containerhelper.hxx"
59 :
60 : using ::com::sun::star::beans::XPropertySet;
61 : using ::com::sun::star::uno::Any;
62 :
63 : using namespace ::com::sun::star;
64 : using namespace ::com::sun::star::text;
65 :
66 : namespace oox {
67 : namespace vml {
68 :
69 : // ============================================================================
70 :
71 : using namespace ::com::sun::star;
72 : using namespace ::com::sun::star::drawing;
73 : using namespace ::com::sun::star::graphic;
74 : using namespace ::com::sun::star::uno;
75 : using namespace ::com::sun::star::io;
76 :
77 : using ::oox::core::XmlFilterBase;
78 :
79 : // ============================================================================
80 :
81 : namespace {
82 :
83 : const sal_Int32 VML_SHAPETYPE_PICTUREFRAME = 75;
84 : const sal_Int32 VML_SHAPETYPE_HOSTCONTROL = 201;
85 :
86 : // ----------------------------------------------------------------------------
87 :
88 1075 : awt::Point lclGetAbsPoint( const awt::Point& rRelPoint, const awt::Rectangle& rShapeRect, const awt::Rectangle& rCoordSys )
89 : {
90 1075 : double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
91 1075 : double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
92 1075 : awt::Point aAbsPoint;
93 1075 : aAbsPoint.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelPoint.X - rCoordSys.X) + 0.5 );
94 1075 : aAbsPoint.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelPoint.Y - rCoordSys.Y) + 0.5 );
95 1075 : return aAbsPoint;
96 : }
97 :
98 24 : awt::Rectangle lclGetAbsRect( const awt::Rectangle& rRelRect, const awt::Rectangle& rShapeRect, const awt::Rectangle& rCoordSys )
99 : {
100 24 : double fWidthRatio = static_cast< double >( rShapeRect.Width ) / rCoordSys.Width;
101 24 : double fHeightRatio = static_cast< double >( rShapeRect.Height ) / rCoordSys.Height;
102 24 : awt::Rectangle aAbsRect;
103 24 : aAbsRect.X = static_cast< sal_Int32 >( rShapeRect.X + fWidthRatio * (rRelRect.X - rCoordSys.X) + 0.5 );
104 24 : aAbsRect.Y = static_cast< sal_Int32 >( rShapeRect.Y + fHeightRatio * (rRelRect.Y - rCoordSys.Y) + 0.5 );
105 24 : aAbsRect.Width = static_cast< sal_Int32 >( fWidthRatio * rRelRect.Width + 0.5 );
106 24 : aAbsRect.Height = static_cast< sal_Int32 >( fHeightRatio * rRelRect.Height + 0.5 );
107 24 : return aAbsRect;
108 : }
109 :
110 : } // namespace
111 :
112 : // ============================================================================
113 :
114 101 : ShapeTypeModel::ShapeTypeModel():
115 : mbAutoHeight( sal_False ),
116 101 : mbVisible( sal_True )
117 : {
118 101 : }
119 :
120 29 : void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource )
121 : {
122 29 : moShapeType.assignIfUsed( rSource.moShapeType );
123 29 : moCoordPos.assignIfUsed( rSource.moCoordPos );
124 29 : moCoordSize.assignIfUsed( rSource.moCoordSize );
125 : /* The style properties position, left, top, width, height, margin-left,
126 : margin-top are not derived from shape template to shape. */
127 29 : maStrokeModel.assignUsed( rSource.maStrokeModel );
128 29 : maFillModel.assignUsed( rSource.maFillModel );
129 29 : moGraphicPath.assignIfUsed( rSource.moGraphicPath );
130 29 : moGraphicTitle.assignIfUsed( rSource.moGraphicTitle );
131 29 : }
132 :
133 : // ----------------------------------------------------------------------------
134 :
135 101 : ShapeType::ShapeType( Drawing& rDrawing ) :
136 101 : mrDrawing( rDrawing )
137 : {
138 101 : }
139 :
140 123 : ShapeType::~ShapeType()
141 : {
142 123 : }
143 :
144 50 : sal_Int32 ShapeType::getShapeType() const
145 : {
146 50 : return maTypeModel.moShapeType.get( 0 );
147 : }
148 :
149 58 : OUString ShapeType::getGraphicPath() const
150 : {
151 58 : return maTypeModel.moGraphicPath.get( OUString() );
152 : }
153 :
154 13 : awt::Rectangle ShapeType::getCoordSystem() const
155 : {
156 13 : Int32Pair aCoordPos = maTypeModel.moCoordPos.get( Int32Pair( 0, 0 ) );
157 13 : Int32Pair aCoordSize = maTypeModel.moCoordSize.get( Int32Pair( 1000, 1000 ) );
158 13 : if( aCoordSize.first == 0 )
159 0 : aCoordSize.first = 1;
160 13 : if( aCoordSize.second == 0 )
161 0 : aCoordSize.second = 1;
162 13 : return awt::Rectangle( aCoordPos.first, aCoordPos.second, aCoordSize.first, aCoordSize.second );
163 : }
164 :
165 77 : awt::Rectangle ShapeType::getRectangle( const ShapeParentAnchor* pParentAnchor ) const
166 : {
167 : return pParentAnchor ?
168 125 : lclGetAbsRect( getRelRectangle(), pParentAnchor->maShapeRect, pParentAnchor->maCoordSys ) :
169 231 : getAbsRectangle();
170 : }
171 :
172 51 : awt::Rectangle ShapeType::getAbsRectangle() const
173 : {
174 51 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
175 :
176 51 : sal_Int32 nWidth = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maWidth, 0, true, true );
177 51 : if ( nWidth == 0 )
178 1 : nWidth = 1;
179 :
180 51 : sal_Int32 nHeight = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maHeight, 0, false, true );
181 51 : if ( nHeight == 0 )
182 0 : nHeight = 1;
183 :
184 51 : sal_Int32 nLeft = ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maLeft, 0, true, true )
185 51 : + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginLeft, 0, true, true );
186 51 : if (nLeft == 0 && maTypeModel.maPosition == "absolute")
187 13 : nLeft = 1;
188 :
189 : return awt::Rectangle(
190 : nLeft,
191 51 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maTop, 0, false, true ) + ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maTypeModel.maMarginTop, 0, false, true ),
192 51 : nWidth, nHeight );
193 : }
194 :
195 21 : awt::Rectangle ShapeType::getRelRectangle() const
196 : {
197 21 : sal_Int32 nWidth = maTypeModel.maWidth.toInt32();
198 21 : if ( nWidth == 0 )
199 0 : nWidth = 1;
200 :
201 21 : sal_Int32 nHeight = maTypeModel.maHeight.toInt32();
202 21 : if ( nHeight == 0 )
203 0 : nHeight = 1;
204 :
205 : return awt::Rectangle(
206 21 : maTypeModel.maLeft.toInt32(),
207 21 : maTypeModel.maTop.toInt32(),
208 42 : nWidth, nHeight );
209 : }
210 :
211 : // ============================================================================
212 :
213 2 : ClientData::ClientData() :
214 : mnObjType( XML_TOKEN_INVALID ),
215 : mnTextHAlign( XML_Left ),
216 : mnTextVAlign( XML_Top ),
217 : mnCol( -1 ),
218 : mnRow( -1 ),
219 : mnChecked( VML_CLIENTDATA_UNCHECKED ),
220 : mnDropStyle( XML_Combo ),
221 : mnDropLines( 1 ),
222 : mnVal( 0 ),
223 : mnMin( 0 ),
224 : mnMax( 0 ),
225 : mnInc( 0 ),
226 : mnPage( 0 ),
227 : mnSelType( XML_Single ),
228 : mnVTEdit( VML_CLIENTDATA_TEXT ),
229 : mbPrintObject( true ),
230 : mbVisible( false ),
231 : mbDde( false ),
232 : mbNo3D( false ),
233 : mbNo3D2( false ),
234 : mbMultiLine( false ),
235 : mbVScroll( false ),
236 2 : mbSecretEdit( false )
237 : {
238 2 : }
239 :
240 : // ----------------------------------------------------------------------------
241 :
242 79 : ShapeModel::ShapeModel()
243 : {
244 79 : }
245 :
246 79 : ShapeModel::~ShapeModel()
247 : {
248 79 : }
249 :
250 36 : TextBox& ShapeModel::createTextBox(ShapeTypeModel& rModel)
251 : {
252 36 : mxTextBox.reset( new TextBox(rModel) );
253 36 : return *mxTextBox;
254 : }
255 :
256 2 : ClientData& ShapeModel::createClientData()
257 : {
258 2 : mxClientData.reset( new ClientData );
259 2 : return *mxClientData;
260 : }
261 :
262 : // ----------------------------------------------------------------------------
263 :
264 79 : ShapeBase::ShapeBase( Drawing& rDrawing ) :
265 79 : ShapeType( rDrawing )
266 : {
267 79 : }
268 :
269 79 : void ShapeBase::finalizeFragmentImport()
270 : {
271 79 : if( maShapeModel.maType.getLength() > 1 )
272 : {
273 37 : OUString aType = maShapeModel.maType;
274 37 : if (aType[ 0 ] == '#')
275 35 : aType = aType.copy(1);
276 37 : if( const ShapeType* pShapeType = mrDrawing.getShapes().getShapeTypeById( aType, true ) )
277 29 : maTypeModel.assignUsed( pShapeType->getTypeModel() );
278 : }
279 79 : }
280 :
281 57 : OUString ShapeBase::getShapeName() const
282 : {
283 57 : if( !maTypeModel.maShapeName.isEmpty() )
284 10 : return maTypeModel.maShapeName;
285 :
286 47 : OUString aBaseName = mrDrawing.getShapeBaseName( *this );
287 47 : if( !aBaseName.isEmpty() )
288 : {
289 1 : sal_Int32 nShapeIdx = mrDrawing.getLocalShapeIndex( getShapeId() );
290 1 : if( nShapeIdx > 0 )
291 1 : return OUStringBuffer( aBaseName ).append( sal_Unicode( ' ' ) ).append( nShapeIdx ).makeStringAndClear();
292 : }
293 :
294 46 : return OUString();
295 : }
296 :
297 15 : const ShapeType* ShapeBase::getChildTypeById( const OUString& ) const
298 : {
299 15 : return 0;
300 : }
301 :
302 0 : const ShapeBase* ShapeBase::getChildById( const OUString& ) const
303 : {
304 0 : return 0;
305 : }
306 :
307 79 : Reference< XShape > ShapeBase::convertAndInsert( const Reference< XShapes >& rxShapes, const ShapeParentAnchor* pParentAnchor ) const
308 : {
309 79 : Reference< XShape > xShape;
310 79 : if( mrDrawing.isShapeSupported( *this ) )
311 : {
312 : /* Calculate shape rectangle. Applications may do something special
313 : according to some imported shape client data (e.g. Excel cell anchor). */
314 78 : awt::Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
315 :
316 78 : if( ((aShapeRect.Width > 0) || (aShapeRect.Height > 0)) && rxShapes.is() )
317 : {
318 78 : xShape = implConvertAndInsert( rxShapes, aShapeRect );
319 78 : if( xShape.is() )
320 : {
321 : // set imported or generated shape name (not supported by form controls)
322 78 : PropertySet aShapeProp( xShape );
323 78 : if( aShapeProp.hasProperty( PROP_Name ) )
324 56 : aShapeProp.setProperty( PROP_Name, getShapeName() );
325 156 : Reference< XControlShape > xControlShape( xShape, uno::UNO_QUERY );
326 78 : if ( xControlShape.is() && !getTypeModel().mbVisible )
327 : {
328 0 : PropertySet aControlShapeProp( xControlShape->getControl() );
329 0 : aControlShapeProp.setProperty( PROP_EnableVisible, uno::makeAny( sal_False ) );
330 : }
331 : /* Notify the drawing that a new shape has been inserted. For
332 : convenience, pass the rectangle that contains position and
333 : size of the shape. */
334 78 : bool bGroupChild = pParentAnchor != 0;
335 156 : mrDrawing.notifyXShapeInserted( xShape, aShapeRect, *this, bGroupChild );
336 : }
337 : }
338 : else
339 : SAL_WARN("oox", "not converting shape, as calculated rectangle is empty");
340 : }
341 79 : return xShape;
342 : }
343 :
344 1 : void ShapeBase::convertFormatting( const Reference< XShape >& rxShape, const ShapeParentAnchor* pParentAnchor ) const
345 : {
346 1 : if( rxShape.is() )
347 : {
348 : /* Calculate shape rectangle. Applications may do something special
349 : according to some imported shape client data (e.g. Excel cell anchor). */
350 1 : awt::Rectangle aShapeRect = calcShapeRectangle( pParentAnchor );
351 :
352 : // convert the shape, if the calculated rectangle is not empty
353 1 : if( (aShapeRect.Width > 0) || (aShapeRect.Height > 0) )
354 : {
355 1 : rxShape->setPosition( awt::Point( aShapeRect.X, aShapeRect.Y ) );
356 1 : rxShape->setSize( awt::Size( aShapeRect.Width, aShapeRect.Height ) );
357 1 : convertShapeProperties( rxShape );
358 : }
359 : }
360 1 : }
361 :
362 : // protected ------------------------------------------------------------------
363 :
364 79 : awt::Rectangle ShapeBase::calcShapeRectangle( const ShapeParentAnchor* pParentAnchor ) const
365 : {
366 : /* Calculate shape rectangle. Applications may do something special
367 : according to some imported shape client data (e.g. Excel cell anchor). */
368 79 : awt::Rectangle aShapeRect;
369 79 : const ClientData* pClientData = getClientData();
370 79 : if( !pClientData || !mrDrawing.convertClientAnchor( aShapeRect, pClientData->maAnchor ) )
371 77 : aShapeRect = getRectangle( pParentAnchor );
372 79 : return aShapeRect;
373 : }
374 :
375 64 : void ShapeBase::convertShapeProperties( const Reference< XShape >& rxShape ) const
376 : {
377 64 : ::oox::drawingml::ShapePropertyMap aPropMap( mrDrawing.getFilter().getModelObjectHelper() );
378 64 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
379 64 : maTypeModel.maStrokeModel.pushToPropMap( aPropMap, rGraphicHelper );
380 64 : maTypeModel.maFillModel.pushToPropMap( aPropMap, rGraphicHelper );
381 :
382 128 : uno::Reference<lang::XServiceInfo> xSInfo(rxShape, uno::UNO_QUERY_THROW);
383 64 : if (xSInfo->supportsService("com.sun.star.text.TextFrame"))
384 : {
385 : // Any other service supporting the ShadowFormat property?
386 21 : maTypeModel.maShadowModel.pushToPropMap(aPropMap, rGraphicHelper);
387 : // TextFrames have BackColor, not FillColor
388 21 : if (aPropMap.hasProperty(PROP_FillColor))
389 : {
390 12 : aPropMap.setProperty(PROP_BackColor, aPropMap[PROP_FillColor]);
391 12 : aPropMap.erase(PROP_FillColor);
392 : }
393 : // And no LineColor property; individual borders can have colors and widths
394 21 : boost::optional<sal_Int32> oLineWidth;
395 21 : if (maTypeModel.maStrokeModel.moWeight.has())
396 12 : oLineWidth.reset(ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maTypeModel.maStrokeModel.moWeight.get(), 0, false, false));
397 21 : if (aPropMap.hasProperty(PROP_LineColor))
398 : {
399 17 : uno::Reference<beans::XPropertySet> xPropertySet(rxShape, uno::UNO_QUERY);
400 : static sal_Int32 aBorders[] = {
401 : PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder
402 : };
403 85 : for (unsigned int i = 0; i < SAL_N_ELEMENTS(aBorders); ++i)
404 : {
405 68 : table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(aBorders[i])).get<table::BorderLine2>();
406 68 : aBorderLine.Color = aPropMap[PROP_LineColor].get<sal_Int32>();
407 68 : if (oLineWidth)
408 48 : aBorderLine.LineWidth = *oLineWidth;
409 68 : aPropMap.setProperty(aBorders[i], uno::makeAny(aBorderLine));
410 : }
411 17 : aPropMap.erase(PROP_LineColor);
412 21 : }
413 : }
414 43 : else if (xSInfo->supportsService("com.sun.star.drawing.CustomShape"))
415 26 : maTypeModel.maTextpathModel.pushToPropMap(aPropMap, rxShape);
416 :
417 128 : PropertySet( rxShape ).setProperties( aPropMap );
418 64 : }
419 :
420 : // ============================================================================
421 :
422 68 : SimpleShape::SimpleShape( Drawing& rDrawing, const OUString& rService ) :
423 : ShapeBase( rDrawing ),
424 68 : maService( rService )
425 : {
426 68 : }
427 :
428 77 : void lcl_setSurround(PropertySet& rPropSet, const ShapeTypeModel& rTypeModel)
429 : {
430 77 : sal_Int32 nSurround = com::sun::star::text::WrapTextMode_THROUGHT;
431 151 : if ( rTypeModel.moWrapType.get() == "square" || rTypeModel.moWrapType .get()== "tight" ||
432 74 : rTypeModel.moWrapType.get() == "through" )
433 : {
434 3 : nSurround = com::sun::star::text::WrapTextMode_PARALLEL;
435 3 : if ( rTypeModel.moWrapSide.get() == "left" )
436 0 : nSurround = com::sun::star::text::WrapTextMode_LEFT;
437 3 : else if ( rTypeModel.moWrapSide.get() == "right" )
438 0 : nSurround = com::sun::star::text::WrapTextMode_RIGHT;
439 : }
440 74 : else if ( rTypeModel.moWrapType.get() == "topAndBottom" )
441 0 : nSurround = com::sun::star::text::WrapTextMode_NONE;
442 :
443 77 : rPropSet.setProperty(PROP_Surround, nSurround);
444 77 : }
445 :
446 77 : void lcl_SetAnchorType(PropertySet& rPropSet, const ShapeTypeModel& rTypeModel)
447 : {
448 77 : if ( rTypeModel.maPositionHorizontal == "center" )
449 9 : rPropSet.setAnyProperty(PROP_HoriOrient, makeAny(text::HoriOrientation::CENTER));
450 :
451 77 : if ( rTypeModel.maPositionHorizontalRelative == "page" )
452 4 : rPropSet.setAnyProperty(PROP_HoriOrientRelation, makeAny(text::RelOrientation::PAGE_FRAME));
453 :
454 77 : if ( rTypeModel.maPositionVertical == "center" )
455 5 : rPropSet.setAnyProperty(PROP_VertOrient, makeAny(text::VertOrientation::CENTER));
456 :
457 77 : if ( rTypeModel.maPosition == "absolute" )
458 : {
459 : // Word supports as-character (inline) and at-character only, absolute can't be inline.
460 61 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AT_CHARACTER);
461 :
462 61 : if ( rTypeModel.maPositionVerticalRelative == "page" )
463 : {
464 3 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::PAGE_FRAME);
465 : }
466 58 : else if ( rTypeModel.maPositionVerticalRelative == "margin" )
467 : {
468 9 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::PAGE_PRINT_AREA);
469 : }
470 : else
471 : {
472 : // Vertical placement relative to margin, because parent style must not modify vertical position
473 49 : rPropSet.setProperty(PROP_VertOrientRelation, text::RelOrientation::FRAME);
474 : }
475 : }
476 16 : else if( rTypeModel.maPosition == "relative" )
477 : { // I'm not very sure this is correct either.
478 0 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AT_PARAGRAPH);
479 : }
480 : else // static (is the default) means anchored inline
481 : {
482 16 : rPropSet.setProperty(PROP_AnchorType, text::TextContentAnchorType_AS_CHARACTER);
483 : }
484 77 : lcl_setSurround( rPropSet, rTypeModel );
485 77 : }
486 :
487 50 : Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
488 : {
489 50 : awt::Rectangle aShapeRect(rShapeRect);
490 50 : boost::optional<sal_Int32> oRotation;
491 50 : if (!maTypeModel.maRotation.isEmpty())
492 3 : oRotation.reset(maTypeModel.maRotation.toInt32());
493 50 : if (!maTypeModel.maFlip.isEmpty())
494 : {
495 3 : if (maTypeModel.maFlip.equalsAscii("x"))
496 : {
497 2 : aShapeRect.X += aShapeRect.Width;
498 2 : aShapeRect.Width *= -1;
499 2 : if (oRotation)
500 1 : oRotation.reset(360 - *oRotation);
501 : }
502 1 : else if (maTypeModel.maFlip.equalsAscii("y"))
503 : {
504 0 : aShapeRect.Y += aShapeRect.Height;
505 0 : aShapeRect.Height *= -1;
506 : }
507 : }
508 :
509 50 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( maService, rxShapes, aShapeRect );
510 50 : convertShapeProperties( xShape );
511 :
512 50 : if ( maService.equalsAscii( "com.sun.star.text.TextFrame" ) )
513 : {
514 21 : PropertySet( xShape ).setAnyProperty( PROP_FrameIsAutomaticHeight, makeAny( maTypeModel.mbAutoHeight ) );
515 21 : PropertySet( xShape ).setAnyProperty( PROP_SizeType, makeAny( maTypeModel.mbAutoHeight ? SizeType::MIN : SizeType::FIX ) );
516 21 : if( getTextBox()->borderDistanceSet )
517 : {
518 21 : PropertySet( xShape ).setAnyProperty( PROP_LeftBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceLeft )));
519 21 : PropertySet( xShape ).setAnyProperty( PROP_TopBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceTop )));
520 21 : PropertySet( xShape ).setAnyProperty( PROP_RightBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceRight )));
521 21 : PropertySet( xShape ).setAnyProperty( PROP_BottomBorderDistance, makeAny( sal_Int32( getTextBox()->borderDistanceBottom )));
522 : }
523 : }
524 : else
525 : {
526 : // FIXME Setting the relative width/heigh only for everything but text frames as
527 : // TextFrames already have relative widht/heigh feature... but currently not working
528 : // in the way we need.
529 :
530 : // Set the relative width / height if any
531 29 : if ( !maTypeModel.maWidthPercent.isEmpty( ) )
532 : {
533 : // Only page-relative width is supported ATM
534 3 : if ( maTypeModel.maWidthRelative.isEmpty() || maTypeModel.maWidthRelative == "page" )
535 : {
536 1 : sal_Int16 nWidth = maTypeModel.maWidthPercent.toInt32() / 10;
537 : // Only apply if nWidth != 0
538 1 : if ( nWidth )
539 1 : PropertySet( xShape ).setAnyProperty(PROP_RelativeWidth, makeAny( nWidth ) );
540 : }
541 : }
542 29 : if ( !maTypeModel.maHeightPercent.isEmpty( ) )
543 : {
544 : // Only page-relative height is supported ATM
545 1 : if ( maTypeModel.maHeightRelative.isEmpty() || maTypeModel.maHeightRelative == "page" )
546 : {
547 1 : sal_Int16 nHeight = maTypeModel.maHeightPercent.toInt32() / 10;
548 : // Only apply if nHeight != 0
549 1 : if ( nHeight )
550 1 : PropertySet( xShape ).setAnyProperty(PROP_RelativeHeight, makeAny( nHeight ) );
551 : }
552 : }
553 :
554 : // drawinglayer default is center, MSO default is top.
555 29 : drawing::TextVerticalAdjust eTextVerticalAdjust = drawing::TextVerticalAdjust_TOP;
556 29 : if (maTypeModel.maVTextAnchor == "middle")
557 0 : eTextVerticalAdjust = drawing::TextVerticalAdjust_CENTER;
558 29 : else if (maTypeModel.maVTextAnchor == "bottom")
559 1 : eTextVerticalAdjust = drawing::TextVerticalAdjust_BOTTOM;
560 29 : PropertySet(xShape).setAnyProperty(PROP_TextVerticalAdjust, makeAny(eTextVerticalAdjust));
561 :
562 29 : if (getTextBox())
563 11 : getTextBox()->convert(xShape);
564 : }
565 :
566 : // Import Legacy Fragments (if any)
567 50 : if( xShape.is() && !maShapeModel.maLegacyDiagramPath.isEmpty() )
568 : {
569 0 : Reference< XInputStream > xInStrm( mrDrawing.getFilter().openInputStream( maShapeModel.maLegacyDiagramPath ), UNO_SET_THROW );
570 0 : if( xInStrm.is() )
571 0 : PropertySet( xShape ).setProperty( PROP_LegacyFragment, xInStrm );
572 : }
573 :
574 100 : PropertySet aPropertySet(xShape);
575 50 : if (xShape.is() && oRotation)
576 : {
577 : // See DffPropertyReader::Fix16ToAngle(): in VML, positive rotation angles are clockwise, we have them as counter-clockwise.
578 : // Additionally, VML type is 0..360, our is 0.36000.
579 3 : aPropertySet.setAnyProperty(PROP_RotateAngle, makeAny(sal_Int32(NormAngle360((*oRotation) * -100))));
580 : // If rotation is used, simple setPosition() is not enough.
581 3 : aPropertySet.setAnyProperty(PROP_HoriOrientPosition, makeAny( aShapeRect.X ) );
582 3 : aPropertySet.setAnyProperty(PROP_VertOrientPosition, makeAny( aShapeRect.Y ) );
583 : }
584 :
585 50 : lcl_SetAnchorType(aPropertySet, maTypeModel);
586 :
587 100 : return xShape;
588 : }
589 :
590 16 : Reference< XShape > SimpleShape::createPictureObject( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect, OUString& rGraphicPath ) const
591 : {
592 16 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.GraphicObjectShape", rxShapes, rShapeRect );
593 16 : if( xShape.is() )
594 : {
595 16 : XmlFilterBase& rFilter = mrDrawing.getFilter();
596 16 : OUString aGraphicUrl = rFilter.getGraphicHelper().importEmbeddedGraphicObject( rGraphicPath );
597 32 : PropertySet aPropSet( xShape );
598 16 : if( !aGraphicUrl.isEmpty() )
599 : {
600 16 : aPropSet.setProperty( PROP_GraphicURL, aGraphicUrl );
601 : }
602 32 : uno::Reference< lang::XServiceInfo > xServiceInfo(rxShapes, uno::UNO_QUERY);
603 : // If the shape has an absolute position, set the properties accordingly, unless we're inside a group shape.
604 16 : if ( maTypeModel.maPosition == "absolute" && !xServiceInfo->supportsService("com.sun.star.drawing.GroupShape"))
605 : {
606 4 : aPropSet.setProperty(PROP_HoriOrientPosition, rShapeRect.X);
607 4 : aPropSet.setProperty(PROP_VertOrientPosition, rShapeRect.Y);
608 4 : aPropSet.setProperty(PROP_Opaque, sal_False);
609 : }
610 :
611 32 : lcl_SetAnchorType(aPropSet, maTypeModel);
612 : }
613 16 : return xShape;
614 : }
615 :
616 : // ============================================================================
617 :
618 21 : RectangleShape::RectangleShape( Drawing& rDrawing ) :
619 21 : SimpleShape( rDrawing, "com.sun.star.drawing.RectangleShape" )
620 : {
621 21 : }
622 :
623 21 : Reference<XShape> RectangleShape::implConvertAndInsert(const Reference<XShapes>& rxShapes, const awt::Rectangle& rShapeRect) const
624 : {
625 21 : OUString aGraphicPath = getGraphicPath();
626 :
627 : // try to create a picture object
628 21 : if(!aGraphicPath.isEmpty())
629 1 : return SimpleShape::createPictureObject(rxShapes, rShapeRect, aGraphicPath);
630 :
631 : // default: try to create a rectangle shape
632 40 : Reference<XShape> xShape = SimpleShape::implConvertAndInsert(rxShapes, rShapeRect);
633 40 : OUString sArcsize = maTypeModel.maArcsize;
634 20 : if ( !sArcsize.isEmpty( ) )
635 : {
636 1 : sal_Unicode cLastChar = sArcsize[sArcsize.getLength() - 1];
637 1 : sal_Int32 nValue = sArcsize.copy( 0, sArcsize.getLength() - 1 ).toInt32( );
638 : // Get the smallest half-side
639 1 : double size = std::min( rShapeRect.Height, rShapeRect.Width ) / 2.0;
640 1 : sal_Int32 nRadius = 0;
641 1 : if ( cLastChar == 'f' )
642 1 : nRadius = size * nValue / 65536;
643 0 : else if ( cLastChar == '%' )
644 0 : nRadius = size * nValue / 100;
645 1 : PropertySet( xShape ).setAnyProperty( PROP_CornerRadius, makeAny( nRadius ) );
646 : }
647 41 : return xShape;
648 : }
649 :
650 : // ============================================================================
651 :
652 2 : EllipseShape::EllipseShape( Drawing& rDrawing ) :
653 2 : SimpleShape( rDrawing, "com.sun.star.drawing.EllipseShape" )
654 : {
655 2 : }
656 :
657 : // ============================================================================
658 :
659 0 : PolyLineShape::PolyLineShape( Drawing& rDrawing ) :
660 0 : SimpleShape( rDrawing, "com.sun.star.drawing.PolyLineShape" )
661 : {
662 0 : }
663 :
664 0 : Reference< XShape > PolyLineShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
665 : {
666 0 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
667 : // polygon path
668 0 : awt::Rectangle aCoordSys = getCoordSystem();
669 0 : if( !maShapeModel.maPoints.empty() && (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
670 : {
671 0 : ::std::vector< awt::Point > aAbsPoints;
672 0 : for( ShapeModel::PointVector::const_iterator aIt = maShapeModel.maPoints.begin(), aEnd = maShapeModel.maPoints.end(); aIt != aEnd; ++aIt )
673 0 : aAbsPoints.push_back( lclGetAbsPoint( *aIt, rShapeRect, aCoordSys ) );
674 0 : PointSequenceSequence aPointSeq( 1 );
675 0 : aPointSeq[ 0 ] = ContainerHelper::vectorToSequence( aAbsPoints );
676 0 : PropertySet aPropSet( xShape );
677 0 : aPropSet.setProperty( PROP_PolyPolygon, aPointSeq );
678 : }
679 0 : return xShape;
680 : }
681 :
682 5 : LineShape::LineShape(Drawing& rDrawing)
683 5 : : SimpleShape(rDrawing, "com.sun.star.drawing.LineShape")
684 : {
685 5 : }
686 :
687 2 : awt::Rectangle LineShape::getAbsRectangle() const
688 : {
689 2 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
690 2 : awt::Rectangle aShapeRect;
691 2 : sal_Int32 nIndex = 0;
692 :
693 2 : aShapeRect.X = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maFrom.getToken(0, ',', nIndex), 0, true, true);
694 2 : aShapeRect.Y = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maFrom.getToken(0, ',', nIndex), 0, false, true);
695 2 : nIndex = 0;
696 2 : aShapeRect.Width = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maTo.getToken(0, ',', nIndex), 0, true, true) - aShapeRect.X;
697 2 : aShapeRect.Height = ConversionHelper::decodeMeasureToHmm(rGraphicHelper, maShapeModel.maTo.getToken(0, ',', nIndex), 0, false, true) - aShapeRect.Y;
698 2 : return aShapeRect;
699 : }
700 :
701 3 : awt::Rectangle LineShape::getRelRectangle() const
702 : {
703 3 : awt::Rectangle aShapeRect;
704 3 : sal_Int32 nIndex = 0;
705 :
706 3 : aShapeRect.X = maShapeModel.maFrom.getToken(0, ',', nIndex).toInt32();
707 3 : aShapeRect.Y = maShapeModel.maFrom.getToken(0, ',', nIndex).toInt32();
708 3 : nIndex = 0;
709 3 : aShapeRect.Width = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.X;
710 3 : aShapeRect.Height = maShapeModel.maTo.getToken(0, ',', nIndex).toInt32() - aShapeRect.Y;
711 3 : return aShapeRect;
712 : }
713 :
714 : // ============================================================================
715 :
716 2 : BezierShape::BezierShape(Drawing& rDrawing)
717 2 : : SimpleShape(rDrawing, "com.sun.star.drawing.OpenBezierShape")
718 : {
719 2 : }
720 :
721 2 : Reference< XShape > BezierShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
722 : {
723 : // If we have an 'x' in the last part of the path it means it is closed...
724 2 : sal_Int32 nPos = maShapeModel.maVmlPath.lastIndexOf(',');
725 2 : if ( nPos != -1 && maShapeModel.maVmlPath.copy(nPos).indexOf('x') != -1 )
726 : {
727 1 : const_cast<BezierShape*>( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
728 : }
729 :
730 2 : awt::Rectangle aCoordSys = getCoordSystem();
731 2 : PolyPolygonBezierCoords aBezierCoords;
732 :
733 2 : if( (aCoordSys.Width > 0) && (aCoordSys.Height > 0) )
734 : {
735 2 : const GraphicHelper& rGraphicHelper = mrDrawing.getFilter().getGraphicHelper();
736 :
737 : // Bezier paths may consist of one or more sub-paths
738 : typedef ::std::vector< ::std::vector< awt::Point > > SubPathList;
739 : typedef ::std::vector< ::std::vector< PolygonFlags > > FlagsList;
740 2 : SubPathList aCoordLists;
741 4 : FlagsList aFlagLists;
742 2 : sal_Int32 nIndex = 0;
743 :
744 : // Curve defined by to, from, control1 and control2 attributes
745 2 : if ( maShapeModel.maVmlPath.isEmpty() )
746 : {
747 0 : aCoordLists.push_back( ::std::vector< awt::Point >() );
748 0 : aFlagLists.push_back( ::std::vector< PolygonFlags >() );
749 :
750 : // Start point
751 0 : aCoordLists[ 0 ].push_back(
752 0 : awt::Point(ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, true, true ),
753 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maFrom.getToken( 0, ',', nIndex ), 0, false, true ) ) );
754 : // Control point 1
755 0 : aCoordLists[ 0 ].push_back(
756 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, true, true ),
757 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl1.getToken( 0, ',', nIndex ), 0, false, true ) ) );
758 : // Control point 2
759 0 : aCoordLists[ 0 ].push_back(
760 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, true, true ),
761 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maControl2.getToken( 0, ',', nIndex ), 0, false, true ) ) );
762 : // End point
763 0 : aCoordLists[ 0 ].push_back(
764 0 : awt::Point( ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, true, true ),
765 0 : ConversionHelper::decodeMeasureToHmm( rGraphicHelper, maShapeModel.maTo.getToken( 0, ',', nIndex ), 0, false, true ) ) );
766 :
767 : // First and last points are normals, points 2 and 4 are controls
768 0 : aFlagLists[ 0 ].resize( aCoordLists[ 0 ].size(), PolygonFlags_CONTROL );
769 0 : aFlagLists[ 0 ][ 0 ] = PolygonFlags_NORMAL;
770 0 : aFlagLists[ 0 ].back() = PolygonFlags_NORMAL;
771 : }
772 : // Curve defined by path attribute
773 : else
774 : {
775 : // Parse VML path string and convert to absolute coordinates
776 2 : ConversionHelper::decodeVmlPath( aCoordLists, aFlagLists, maShapeModel.maVmlPath );
777 :
778 132 : for ( SubPathList::iterator aListIt = aCoordLists.begin(); aListIt != aCoordLists.end(); ++aListIt )
779 1205 : for ( ::std::vector< awt::Point >::iterator aPointIt = (*aListIt).begin(); aPointIt != (*aListIt).end(); ++aPointIt)
780 : {
781 1075 : (*aPointIt) = lclGetAbsPoint( (*aPointIt), rShapeRect, aCoordSys );
782 : }
783 : }
784 :
785 2 : aBezierCoords.Coordinates.realloc( aCoordLists.size() );
786 132 : for ( unsigned int i = 0; i < aCoordLists.size(); i++ )
787 130 : aBezierCoords.Coordinates[i] = ContainerHelper::vectorToSequence( aCoordLists[i] );
788 :
789 2 : aBezierCoords.Flags.realloc( aFlagLists.size() );
790 132 : for ( unsigned int i = 0; i < aFlagLists.size(); i++ )
791 130 : aBezierCoords.Flags[i] = ContainerHelper::vectorToSequence( aFlagLists[i] );
792 :
793 6 : if( !aCoordLists.front().empty() && !aCoordLists.back().empty()
794 2 : && aCoordLists.front().front().X == aCoordLists.back().back().X
795 2 : && aCoordLists.front().front().Y == aCoordLists.back().back().Y )
796 : { // HACK: If the shape is in fact closed, which can be found out only when the path is known,
797 : // force to closed bezier shape (otherwise e.g. fill won't work).
798 0 : const_cast< BezierShape* >( this )->setService( "com.sun.star.drawing.ClosedBezierShape" );
799 2 : }
800 : }
801 :
802 2 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
803 :
804 2 : if( aBezierCoords.Coordinates.hasElements())
805 : {
806 2 : PropertySet aPropSet( xShape );
807 2 : aPropSet.setProperty( PROP_PolyPolygonBezier, aBezierCoords );
808 : }
809 :
810 : // Hacky way of ensuring the shape is correctly sized/positioned
811 2 : xShape->setSize( awt::Size( rShapeRect.Width, rShapeRect.Height ) );
812 2 : xShape->setPosition( awt::Point( rShapeRect.X, rShapeRect.Y ) );
813 2 : return xShape;
814 : }
815 :
816 : // ============================================================================
817 :
818 38 : CustomShape::CustomShape( Drawing& rDrawing ) :
819 38 : SimpleShape( rDrawing, "com.sun.star.drawing.CustomShape" )
820 : {
821 38 : }
822 :
823 21 : Reference< XShape > CustomShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
824 : {
825 : // try to create a custom shape
826 21 : Reference< XShape > xShape = SimpleShape::implConvertAndInsert( rxShapes, rShapeRect );
827 21 : if( xShape.is() ) try
828 : {
829 : // create the custom shape geometry
830 21 : Reference< XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY_THROW );
831 13 : xDefaulter->createCustomShapeDefaults( OUString::valueOf( getShapeType() ) );
832 : // convert common properties
833 13 : convertShapeProperties( xShape );
834 : }
835 8 : catch( Exception& )
836 : {
837 : }
838 21 : return xShape;
839 : }
840 :
841 : // ============================================================================
842 :
843 38 : ComplexShape::ComplexShape( Drawing& rDrawing ) :
844 38 : CustomShape( rDrawing )
845 : {
846 38 : }
847 :
848 37 : Reference< XShape > ComplexShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
849 : {
850 37 : XmlFilterBase& rFilter = mrDrawing.getFilter();
851 37 : sal_Int32 nShapeType = getShapeType();
852 37 : OUString aGraphicPath = getGraphicPath();
853 :
854 : // try to find registered OLE object info
855 37 : if( const OleObjectInfo* pOleObjectInfo = mrDrawing.getOleObjectInfo( maTypeModel.maShapeId ) )
856 : {
857 : OSL_ENSURE( nShapeType == VML_SHAPETYPE_PICTUREFRAME, "ComplexShape::implConvertAndInsert - unexpected shape type" );
858 :
859 : // if OLE object is embedded into a DrawingML shape (PPTX), do not create it here
860 0 : if( pOleObjectInfo->mbDmlShape )
861 0 : return Reference< XShape >();
862 :
863 0 : PropertyMap aOleProps;
864 0 : awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height );
865 0 : if( rFilter.getOleObjectHelper().importOleObject( aOleProps, *pOleObjectInfo, aOleSize ) )
866 : {
867 0 : Reference< XShape > xShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.OLE2Shape", rxShapes, rShapeRect );
868 0 : if( xShape.is() )
869 : {
870 : // set the replacement graphic
871 0 : if( !aGraphicPath.isEmpty() )
872 : {
873 0 : Reference< XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath );
874 0 : if( xGraphic.is() )
875 0 : aOleProps[ PROP_Graphic ] <<= xGraphic;
876 : }
877 :
878 0 : PropertySet aPropSet( xShape );
879 0 : aPropSet.setProperties( aOleProps );
880 :
881 0 : return xShape;
882 0 : }
883 0 : }
884 : }
885 :
886 : // try to find registered form control info
887 37 : const ControlInfo* pControlInfo = mrDrawing.getControlInfo( maTypeModel.maShapeId );
888 37 : if( pControlInfo && !pControlInfo->maFragmentPath.isEmpty() )
889 : {
890 : OSL_ENSURE( nShapeType == VML_SHAPETYPE_HOSTCONTROL, "ComplexShape::implConvertAndInsert - unexpected shape type" );
891 0 : OUString aShapeName = getShapeName();
892 0 : if( !aShapeName.isEmpty() )
893 : {
894 : OSL_ENSURE( aShapeName == pControlInfo->maName, "ComplexShape::implConvertAndInsert - control name mismatch" );
895 : // load the control properties from fragment
896 0 : ::oox::ole::EmbeddedControl aControl( aShapeName );
897 0 : if( rFilter.importFragment( new ::oox::ole::AxControlFragment( rFilter, pControlInfo->maFragmentPath, aControl ) ) )
898 : {
899 : // create and return the control shape (including control model)
900 0 : sal_Int32 nCtrlIndex = -1;
901 0 : Reference< XShape > xShape = mrDrawing.createAndInsertXControlShape( aControl, rxShapes, rShapeRect, nCtrlIndex );
902 : // on error, proceed and try to create picture from replacement image
903 0 : if( xShape.is() )
904 0 : return xShape;
905 0 : }
906 0 : }
907 : }
908 :
909 : // host application wants to create the shape (do not try failed OLE controls again)
910 37 : if( (nShapeType == VML_SHAPETYPE_HOSTCONTROL) && !pControlInfo )
911 : {
912 : OSL_ENSURE( getClientData(), "ComplexShape::implConvertAndInsert - missing client data" );
913 1 : Reference< XShape > xShape = mrDrawing.createAndInsertClientXShape( *this, rxShapes, rShapeRect );
914 1 : if( xShape.is() )
915 1 : return xShape;
916 : }
917 :
918 : // try to create a picture object
919 36 : if( !aGraphicPath.isEmpty() )
920 15 : return SimpleShape::createPictureObject(rxShapes, rShapeRect, aGraphicPath);
921 :
922 : // default: try to create a custom shape
923 21 : return CustomShape::implConvertAndInsert( rxShapes, rShapeRect );
924 : }
925 :
926 : // ============================================================================
927 :
928 11 : GroupShape::GroupShape( Drawing& rDrawing ) :
929 : ShapeBase( rDrawing ),
930 11 : mxChildren( new ShapeContainer( rDrawing ) )
931 : {
932 11 : }
933 :
934 22 : GroupShape::~GroupShape()
935 : {
936 22 : }
937 :
938 11 : void GroupShape::finalizeFragmentImport()
939 : {
940 : // basic shape processing
941 11 : ShapeBase::finalizeFragmentImport();
942 : // finalize all child shapes
943 11 : mxChildren->finalizeFragmentImport();
944 11 : }
945 :
946 19 : const ShapeType* GroupShape::getChildTypeById( const OUString& rShapeId ) const
947 : {
948 19 : return mxChildren->getShapeTypeById( rShapeId, true );
949 : }
950 :
951 0 : const ShapeBase* GroupShape::getChildById( const OUString& rShapeId ) const
952 : {
953 0 : return mxChildren->getShapeById( rShapeId, true );
954 : }
955 :
956 11 : Reference< XShape > GroupShape::implConvertAndInsert( const Reference< XShapes >& rxShapes, const awt::Rectangle& rShapeRect ) const
957 : {
958 11 : Reference< XShape > xGroupShape;
959 : // check that this shape contains children and a valid coordinate system
960 11 : ShapeParentAnchor aParentAnchor;
961 11 : aParentAnchor.maShapeRect = rShapeRect;
962 11 : aParentAnchor.maCoordSys = getCoordSystem();
963 11 : if( !mxChildren->empty() && (aParentAnchor.maCoordSys.Width > 0) && (aParentAnchor.maCoordSys.Height > 0) ) try
964 : {
965 11 : xGroupShape = mrDrawing.createAndInsertXShape( "com.sun.star.drawing.GroupShape", rxShapes, rShapeRect );
966 11 : Reference< XShapes > xChildShapes( xGroupShape, UNO_QUERY_THROW );
967 11 : mxChildren->convertAndInsert( xChildShapes, &aParentAnchor );
968 11 : if( !xChildShapes->hasElements() )
969 : {
970 : SAL_WARN("oox", "no child shape has been created - deleting the group shape");
971 0 : rxShapes->remove( xGroupShape );
972 0 : xGroupShape.clear();
973 11 : }
974 : }
975 0 : catch( Exception& )
976 : {
977 : }
978 : // Make sure group shapes are inline as well, unless there is an explicit different style.
979 22 : PropertySet aPropertySet(xGroupShape);
980 11 : lcl_SetAnchorType(aPropertySet, maTypeModel);
981 22 : return xGroupShape;
982 : }
983 :
984 : // ============================================================================
985 :
986 : } // namespace vml
987 141 : } // namespace oox
988 :
989 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|