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