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