fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / oox / source / drawingml / customshapeproperties.cxx
blob12c7c3f85d0cc581e88bf2df81c51c9bf011083b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "drawingml/customshapeproperties.hxx"
21 #include "oox/helper/helper.hxx"
22 #include "oox/helper/propertymap.hxx"
23 #include "oox/helper/propertyset.hxx"
24 #include "oox/token/tokenmap.hxx"
25 #include <com/sun/star/awt/Rectangle.hpp>
26 #include <com/sun/star/awt/Size.hpp>
27 #include <com/sun/star/beans/XMultiPropertySet.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/graphic/XGraphicTransformer.hpp>
30 #include <com/sun/star/drawing/XShape.hpp>
31 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
32 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
33 #include <osl/diagnose.h>
35 using namespace ::oox::core;
36 using namespace ::com::sun::star;
37 using namespace ::com::sun::star::uno;
38 using namespace ::com::sun::star::beans;
39 using namespace ::com::sun::star::graphic;
40 using namespace ::com::sun::star::drawing;
42 namespace oox { namespace drawingml {
44 CustomShapeProperties::CustomShapeProperties()
45 : mnShapePresetType ( -1 )
46 , mbShapeTypeOverride(false)
47 , mbMirroredX ( false )
48 , mbMirroredY ( false )
49 , mnTextRotateAngle ( 0 )
50 , mnArcNum ( 0 )
53 CustomShapeProperties::~CustomShapeProperties()
57 uno::Sequence< sal_Int8 > CustomShapeProperties::getShapePresetTypeName() const
59 return StaticTokenMap::get().getUtf8TokenName( mnShapePresetType );
62 sal_Int32 CustomShapeProperties::SetCustomShapeGuideValue( std::vector< CustomShapeGuide >& rGuideList, const CustomShapeGuide& rGuide )
64 sal_uInt32 nIndex = 0;
65 for( ; nIndex < rGuideList.size(); nIndex++ )
67 if ( rGuideList[ nIndex ].maName == rGuide.maName )
68 break;
70 if ( nIndex == rGuideList.size() )
71 rGuideList.push_back( rGuide );
72 return static_cast< sal_Int32 >( nIndex );
75 // returns the index into the guidelist for a given formula name,
76 // if the return value is < 0 then the guide value could not be found
77 sal_Int32 CustomShapeProperties::GetCustomShapeGuideValue( const std::vector< CustomShapeGuide >& rGuideList, const OUString& rFormulaName )
79 // traverse the list from the end, because guide names can be reused
80 // and current is the last one
81 // see a1 guide in gear6 custom shape preset as example
82 sal_Int32 nIndex = static_cast< sal_Int32 >( rGuideList.size() ) - 1;
83 for( ; nIndex >= 0; nIndex-- )
85 if ( rGuideList[ nIndex ].maName == rFormulaName )
86 break;
89 return nIndex;
92 CustomShapeProperties::PresetDataMap CustomShapeProperties::maPresetDataMap;
94 static OUString GetConnectorShapeType( sal_Int32 nType )
96 SAL_INFO(
97 "oox.drawingml", "preset: " << nType << " " << XML_straightConnector1);
99 OUString sType;
100 switch( nType )
102 case XML_straightConnector1:
103 sType = "mso-spt32";
104 break;
105 default:
106 break;
108 return sType;
111 void CustomShapeProperties::pushToPropSet( const ::oox::core::FilterBase& /* rFilterBase */,
112 const Reference < XPropertySet >& xPropSet, const Reference < XShape > & xShape, const awt::Size &aSize )
114 if ( mnShapePresetType >= 0 )
116 SAL_INFO("oox.drawingml", "preset: " << mnShapePresetType);
118 if (maPresetDataMap.empty())
119 initializePresetDataMap();
121 PropertyMap aPropertyMap;
122 PropertySet aPropSet( xPropSet );
124 OUString sConnectorShapeType = GetConnectorShapeType( mnShapePresetType );
126 if (sConnectorShapeType.getLength() > 0)
128 SAL_INFO(
129 "oox.drawingml",
130 "connector shape: " << sConnectorShapeType << " ("
131 << mnShapePresetType << ")");
132 //const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY );
133 Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY );
134 if( xDefaulter.is() ) {
135 xDefaulter->createCustomShapeDefaults( sConnectorShapeType );
136 aPropertyMap.setProperty( PROP_Type, sConnectorShapeType );
139 else if (maPresetDataMap.find(mnShapePresetType) != maPresetDataMap.end())
141 SAL_INFO(
142 "oox.drawingml",
143 "found property map for preset: " << mnShapePresetType);
145 aPropertyMap = maPresetDataMap[mnShapePresetType];
146 #ifdef DEBUG
147 aPropertyMap.dumpCode();
148 #endif
151 aPropertyMap.setProperty( PROP_MirroredX, mbMirroredX );
152 aPropertyMap.setProperty( PROP_MirroredY, mbMirroredY );
153 aPropertyMap.setProperty( PROP_TextPreRotateAngle, mnTextRotateAngle );
154 aPropertyMap.setProperty( PROP_IsPostRotateAngle, true); // For OpenXML Imports
155 Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence();
156 aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq );
158 const OUString sCustomShapeGeometry("CustomShapeGeometry");
159 uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry );
160 uno::Sequence< beans::PropertyValue > aGeoPropSeq;
162 sal_Int32 i, nCount = 0;
163 if (aGeoPropSet >>= aGeoPropSeq)
165 nCount = aGeoPropSeq.getLength();
166 for ( i = 0; i < nCount; i++ )
168 const OUString sAdjustmentValues("AdjustmentValues");
169 if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) )
171 OUString presetTextWarp;
172 if ( aGeoPropSeq[ i ].Value >>= presetTextWarp )
174 aPropertyMap.setProperty( PROP_PresetTextWarp, Any( presetTextWarp ) );
180 if ( maAdjustmentGuideList.size() )
182 const OUString sType = "Type";
183 if ( aGeoPropSet >>= aGeoPropSeq )
185 nCount = aGeoPropSeq.getLength();
186 for ( i = 0; i < nCount; i++ )
188 const OUString sAdjustmentValues("AdjustmentValues");
189 if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) )
191 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq;
192 if ( aGeoPropSeq[ i ].Value >>= aAdjustmentSeq )
194 int nIndex=0;
195 for (std::vector< CustomShapeGuide >::const_iterator aIter( maAdjustmentGuideList.begin() ), aEnd(maAdjustmentGuideList.end());
196 aIter != aEnd; ++aIter)
198 if ( (*aIter).maName.getLength() > 3 )
200 sal_Int32 nAdjustmentIndex = (*aIter).maName.copy( 3 ).toInt32() - 1;
201 if ( ( nAdjustmentIndex >= 0 ) && ( nAdjustmentIndex < aAdjustmentSeq.getLength() ) )
203 EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
204 aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32();
205 aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
206 aAdjustmentVal.Name = (*aIter).maName;
207 aAdjustmentSeq[ nAdjustmentIndex ] = aAdjustmentVal;
209 } else if ( aAdjustmentSeq.getLength() > 0 ) {
210 EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
211 aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32();
212 aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
213 aAdjustmentVal.Name = (*aIter).maName;
214 aAdjustmentSeq[ nIndex++ ] = aAdjustmentVal;
217 aGeoPropSeq[ i ].Value <<= aAdjustmentSeq;
218 xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) );
221 else if ( aGeoPropSeq[ i ].Name.equals( sType ) )
223 if ( sConnectorShapeType.getLength() > 0 )
224 aGeoPropSeq[ i ].Value <<= sConnectorShapeType;
225 else
226 aGeoPropSeq[ i ].Value <<= OUString( "ooxml-CustomShape" );
232 else
234 sal_uInt32 i;
235 PropertyMap aPropertyMap;
236 aPropertyMap.setProperty( PROP_Type, OUString( "ooxml-non-primitive" ));
237 aPropertyMap.setProperty( PROP_MirroredX, mbMirroredX );
238 aPropertyMap.setProperty( PROP_MirroredY, mbMirroredY );
239 // Note 1: If Equations are defined - they are processed using internal div by 360 coordinates
240 // while if they are not, standard ooxml coordinates are used.
241 // This size specifically affects scaling.
242 // Note 2: Width and Height are set to 0 to force scaling to 1.
243 awt::Rectangle aViewBox( 0, 0, aSize.Width, aSize.Height );
244 if( maGuideList.size() )
245 aViewBox = awt::Rectangle( 0, 0, 0, 0 );
246 aPropertyMap.setProperty( PROP_ViewBox, aViewBox);
248 Sequence< EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( maAdjustmentGuideList.size() );
249 for ( i = 0; i < maAdjustmentGuideList.size(); i++ )
251 EnhancedCustomShapeAdjustmentValue aAdjustmentVal;
252 aAdjustmentVal.Value <<= maAdjustmentGuideList[ i ].maFormula.toInt32();
253 aAdjustmentVal.State = PropertyState_DIRECT_VALUE;
254 aAdjustmentVal.Name = maAdjustmentGuideList[ i ].maName;
255 aAdjustmentValues[ i ] = aAdjustmentVal;
257 aPropertyMap.setProperty( PROP_AdjustmentValues, aAdjustmentValues);
259 PropertyMap aPath;
261 Sequence< EnhancedCustomShapeSegment > aSegments( maSegments.size() );
262 for ( i = 0; i < maSegments.size(); i++ )
263 aSegments[ i ] = maSegments[ i ];
264 aPath.setProperty( PROP_Segments, aSegments);
266 if ( maTextRect.has() ) {
267 Sequence< EnhancedCustomShapeTextFrame > aTextFrames(1);
268 aTextFrames[0].TopLeft.First = maTextRect.get().l;
269 aTextFrames[0].TopLeft.Second = maTextRect.get().t;
270 aTextFrames[0].BottomRight.First = maTextRect.get().r;
271 aTextFrames[0].BottomRight.Second = maTextRect.get().b;
272 aPath.setProperty( PROP_TextFrames, aTextFrames);
275 sal_uInt32 j, k, nParameterPairs = 0;
276 for ( i = 0; i < maPath2DList.size(); i++ )
277 nParameterPairs += maPath2DList[ i ].parameter.size();
279 Sequence< EnhancedCustomShapeParameterPair > aParameterPairs( nParameterPairs );
280 for ( i = 0, k = 0; i < maPath2DList.size(); i++ )
281 for ( j = 0; j < maPath2DList[ i ].parameter.size(); j++ )
282 aParameterPairs[ k++ ] = maPath2DList[ i ].parameter[ j ];
283 aPath.setProperty( PROP_Coordinates, aParameterPairs);
285 if ( maPath2DList.size() )
287 bool bAllZero = true;
288 for ( i=0; i < maPath2DList.size(); i++ )
290 if ( maPath2DList[i].w || maPath2DList[i].h ) {
291 bAllZero = false;
292 break;
296 if ( !bAllZero ) {
297 Sequence< awt::Size > aSubViewSize( maPath2DList.size() );
298 for ( i=0; i < maPath2DList.size(); i++ )
300 aSubViewSize[i].Width = static_cast< sal_Int32 >( maPath2DList[i].w );
301 aSubViewSize[i].Height = static_cast< sal_Int32 >( maPath2DList[i].h );
302 SAL_INFO(
303 "oox.cscode",
304 "set subpath " << i << " size: " << maPath2DList[i].w
305 << " x " << maPath2DList[i].h);
307 aPath.setProperty( PROP_SubViewSize, aSubViewSize);
311 Sequence< PropertyValue > aPathSequence = aPath.makePropertyValueSequence();
312 aPropertyMap.setProperty( PROP_Path, aPathSequence);
314 Sequence< OUString > aEquations( maGuideList.size() );
315 for ( i = 0; i < maGuideList.size(); i++ )
316 aEquations[ i ] = maGuideList[ i ].maFormula;
317 aPropertyMap.setProperty( PROP_Equations, aEquations);
319 Sequence< PropertyValues > aHandles( maAdjustHandleList.size() );
320 for ( i = 0; i < maAdjustHandleList.size(); i++ )
322 PropertyMap aHandle;
323 // maAdjustmentHandle[ i ].gdRef1 ... maAdjustmentHandle[ i ].gdRef2 ... :(
324 // gdRef1 && gdRef2 -> we do not offer such reference, so it is difficult
325 // to determine the correct adjustment handle that should be updated with the adjustment
326 // position. here is the solution: the adjustment value that is used within the position
327 // has to be updated, in case the position is a formula the first usage of a
328 // adjustment value is decisive
329 if ( maAdjustHandleList[ i ].polar )
331 aHandle.setProperty( PROP_Position, maAdjustHandleList[ i ].pos);
332 if ( maAdjustHandleList[ i ].min1.has() )
333 aHandle.setProperty( PROP_RadiusRangeMinimum, maAdjustHandleList[ i ].min1.get());
334 if ( maAdjustHandleList[ i ].max1.has() )
335 aHandle.setProperty( PROP_RadiusRangeMaximum, maAdjustHandleList[ i ].max1.get());
337 /* TODO: AngleMin & AngleMax
338 if ( maAdjustHandleList[ i ].min2.has() )
339 aHandle.setProperty( PROP_ ] = maAdjustHandleList[ i ].min2.get());
340 if ( maAdjustHandleList[ i ].max2.has() )
341 aHandle.setProperty( PROP_ ] = maAdjustHandleList[ i ].max2.get());
344 else
346 aHandle.setProperty( PROP_Position, maAdjustHandleList[ i ].pos);
347 if ( maAdjustHandleList[ i ].gdRef1.has() )
349 // TODO: PROP_RefX and PROP_RefY are not yet part of our file format,
350 // so the handles will not work after save/reload
351 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef1.get() );
352 if ( nIndex >= 0 )
353 aHandle.setProperty( PROP_RefX, nIndex);
355 if ( maAdjustHandleList[ i ].gdRef2.has() )
357 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef2.get() );
358 if ( nIndex >= 0 )
359 aHandle.setProperty( PROP_RefY, nIndex);
361 if ( maAdjustHandleList[ i ].min1.has() )
362 aHandle.setProperty( PROP_RangeXMinimum, maAdjustHandleList[ i ].min1.get());
363 if ( maAdjustHandleList[ i ].max1.has() )
364 aHandle.setProperty( PROP_RangeXMaximum, maAdjustHandleList[ i ].max1.get());
365 if ( maAdjustHandleList[ i ].min2.has() )
366 aHandle.setProperty( PROP_RangeYMinimum, maAdjustHandleList[ i ].min2.get());
367 if ( maAdjustHandleList[ i ].max2.has() )
368 aHandle.setProperty( PROP_RangeYMaximum, maAdjustHandleList[ i ].max2.get());
370 aHandles[ i ] = aHandle.makePropertyValueSequence();
372 aPropertyMap.setProperty( PROP_Handles, aHandles);
374 #ifdef DEBUG
375 SAL_INFO("oox.cscode", "==cscode== begin");
376 aPropertyMap.dumpCode();
377 SAL_INFO("oox.cscode", "==cscode== end");
378 SAL_INFO("oox.csdata", "==csdata== begin");
379 aPropertyMap.dumpData();
380 SAL_INFO("oox.csdata", "==csdata== end");
381 #endif
382 // converting the vector to a sequence
383 Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence();
384 PropertySet aPropSet( xPropSet );
385 aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq );
391 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */