1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #include "oox/drawingml/customshapeproperties.hxx" 25 #include "oox/helper/helper.hxx" 26 #include "oox/helper/propertymap.hxx" 27 #include "oox/helper/propertyset.hxx" 28 #include <com/sun/star/awt/Rectangle.hpp> 29 #include <com/sun/star/beans/XMultiPropertySet.hpp> 30 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 31 #include <com/sun/star/graphic/XGraphicTransformer.hpp> 32 #include <com/sun/star/drawing/XShape.hpp> 33 #include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp> 34 35 using rtl::OUString; 36 using namespace ::oox::core; 37 using namespace ::com::sun::star; 38 using namespace ::com::sun::star::uno; 39 using namespace ::com::sun::star::beans; 40 using namespace ::com::sun::star::graphic; 41 using namespace ::com::sun::star::drawing; 42 43 namespace oox { namespace drawingml { 44 45 CustomShapeProperties::CustomShapeProperties() 46 : mbMirroredX ( sal_False ) 47 , mbMirroredY ( sal_False ) 48 , mnTextRotation(0) // #119920# Add missing extra text rotation 49 { 50 } 51 CustomShapeProperties::~CustomShapeProperties() 52 { 53 } 54 55 sal_Int32 CustomShapeProperties::SetCustomShapeGuideValue( std::vector< CustomShapeGuide >& rGuideList, const CustomShapeGuide& rGuide ) 56 { 57 sal_uInt32 nIndex = 0; 58 for( ; nIndex < rGuideList.size(); nIndex++ ) 59 { 60 if ( rGuideList[ nIndex ].maName == rGuide.maName ) 61 break; 62 } 63 if ( nIndex == rGuideList.size() ) 64 rGuideList.push_back( rGuide ); 65 return static_cast< sal_Int32 >( nIndex ); 66 } 67 68 // returns the index into the guidelist for a given formula name, 69 // if the return value is < 0 then the guide value could not be found 70 sal_Int32 CustomShapeProperties::GetCustomShapeGuideValue( const std::vector< CustomShapeGuide >& rGuideList, const rtl::OUString& rFormulaName ) 71 { 72 sal_Int32 nIndex = 0; 73 for( ; nIndex < static_cast< sal_Int32 >( rGuideList.size() ); nIndex++ ) 74 { 75 if ( rGuideList[ nIndex ].maName == rFormulaName ) 76 break; 77 } 78 if ( nIndex == static_cast< sal_Int32 >( rGuideList.size() ) ) 79 nIndex = -1; 80 return nIndex; 81 } 82 83 void CustomShapeProperties::apply( const CustomShapePropertiesPtr& /* rSourceCustomShapeProperties */ ) 84 { 85 // not sure if this needs to be implemented 86 } 87 88 void CustomShapeProperties::pushToPropSet( const ::oox::core::FilterBase& /* rFilterBase */, 89 const Reference < XPropertySet >& xPropSet, const Reference < XShape > & xShape ) const 90 { 91 if ( maShapePresetType.getLength() ) 92 { 93 //const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY ); 94 Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY ); 95 if( xDefaulter.is() ) 96 xDefaulter->createCustomShapeDefaults( maShapePresetType ); 97 98 PropertyMap aPropertyMap; 99 100 aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX ); 101 aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY ); 102 103 if(mnTextRotation) 104 { 105 // #119920# Handle missing text rotation 106 aPropertyMap[ PROP_TextRotateAngle ] <<= Any(mnTextRotation); 107 } 108 109 // converting the vector to a sequence 110 Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence(); 111 PropertySet aPropSet( xPropSet ); 112 aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq ); 113 114 if ( maAdjustmentGuideList.size() ) 115 { 116 const OUString sType = CREATE_OUSTRING( "Type" ); 117 const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) ); 118 uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry ); 119 uno::Sequence< beans::PropertyValue > aGeoPropSeq; 120 if ( aGeoPropSet >>= aGeoPropSeq ) 121 { 122 sal_Int32 i, nCount = aGeoPropSeq.getLength(); 123 for ( i = 0; i < nCount; i++ ) 124 { 125 const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) ); 126 if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) ) 127 { 128 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq; 129 if ( aGeoPropSeq[ i ].Value >>= aAdjustmentSeq ) 130 { 131 std::vector< CustomShapeGuide >::const_iterator aIter( maAdjustmentGuideList.begin() ); 132 while( aIter != maAdjustmentGuideList.end() ) 133 { 134 if ( (*aIter).maName.getLength() > 3 ) 135 { 136 sal_Int32 nAdjustmentIndex = (*aIter).maName.copy( 3 ).toInt32() - 1; 137 if ( ( nAdjustmentIndex >= 0 ) && ( nAdjustmentIndex < aAdjustmentSeq.getLength() ) ) 138 { 139 EnhancedCustomShapeAdjustmentValue aAdjustmentVal; 140 aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32(); 141 aAdjustmentVal.State = PropertyState_DIRECT_VALUE; 142 aAdjustmentSeq[ nAdjustmentIndex ] = aAdjustmentVal; 143 } 144 } 145 aIter++; 146 } 147 aGeoPropSeq[ i ].Value <<= aAdjustmentSeq; 148 xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) ); 149 } 150 } 151 else if ( aGeoPropSeq[ i ].Name.equals( sType ) ) 152 { 153 aGeoPropSeq[ i ].Value <<= maShapePresetType; 154 } 155 } 156 } 157 } 158 } 159 else 160 { 161 sal_uInt32 i; 162 PropertyMap aPropertyMap; 163 aPropertyMap[ PROP_Type ] <<= CREATE_OUSTRING( "non-primitive" ); 164 aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX ); 165 aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY ); 166 167 if(mnTextRotation) 168 { 169 aPropertyMap[ PROP_TextRotation ] <<= Any(mnTextRotation); 170 } 171 172 awt::Size aSize( xShape->getSize() ); 173 awt::Rectangle aViewBox( 0, 0, aSize.Width * 360, aSize.Height * 360 ); 174 if ( maPath2DList.size() ) 175 { // TODO: each polygon may have its own size, but I think it is rather been used 176 // so we are only taking care of the first 177 if ( maPath2DList[ 0 ].w ) 178 aViewBox.Width = static_cast< sal_Int32 >( maPath2DList[ 0 ].w ); 179 if ( maPath2DList[ 0 ].h ) 180 aViewBox.Height = static_cast< sal_Int32 >( maPath2DList[ 0 ].h ); 181 } 182 aPropertyMap[ PROP_ViewBox ] <<= aViewBox; 183 184 Sequence< EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( maAdjustmentGuideList.size() ); 185 for ( i = 0; i < maAdjustmentGuideList.size(); i++ ) 186 { 187 EnhancedCustomShapeAdjustmentValue aAdjustmentVal; 188 aAdjustmentVal.Value <<= maAdjustmentGuideList[ i ].maFormula.toInt32(); 189 aAdjustmentVal.State = PropertyState_DIRECT_VALUE; 190 aAdjustmentValues[ i ] = aAdjustmentVal; 191 } 192 aPropertyMap[ PROP_AdjustmentValues ] <<= aAdjustmentValues; 193 194 Sequence< rtl::OUString > aEquations( maGuideList.size() ); 195 for ( i = 0; i < maGuideList.size(); i++ ) 196 aEquations[ i ] = maGuideList[ i ].maFormula; 197 aPropertyMap[ PROP_Equations ] <<= aEquations; 198 199 PropertyMap aPath; 200 Sequence< EnhancedCustomShapeSegment > aSegments( maSegments.size() ); 201 for ( i = 0; i < maSegments.size(); i++ ) 202 aSegments[ i ] = maSegments[ i ]; 203 aPath[ PROP_Segments ] <<= aSegments; 204 sal_uInt32 j, k, nParameterPairs = 0; 205 for ( i = 0; i < maPath2DList.size(); i++ ) 206 nParameterPairs += maPath2DList[ i ].parameter.size(); 207 Sequence< EnhancedCustomShapeParameterPair > aParameterPairs( nParameterPairs ); 208 for ( i = 0, k = 0; i < maPath2DList.size(); i++ ) 209 for ( j = 0; j < maPath2DList[ i ].parameter.size(); j++ ) 210 aParameterPairs[ k++ ] = maPath2DList[ i ].parameter[ j ]; 211 aPath[ PROP_Coordinates ] <<= aParameterPairs; 212 Sequence< PropertyValue > aPathSequence = aPath.makePropertyValueSequence(); 213 aPropertyMap[ PROP_Path ] <<= aPathSequence; 214 215 Sequence< PropertyValues > aHandles( maAdjustHandleList.size() ); 216 for ( i = 0; i < maAdjustHandleList.size(); i++ ) 217 { 218 PropertyMap aHandle; 219 // maAdjustmentHandle[ i ].gdRef1 ... maAdjustmentHandle[ i ].gdRef2 ... :( 220 // gdRef1 && gdRef2 -> we do not offer such reference, so it is difficult 221 // to determine the correct adjustment handle that should be updated with the adjustment 222 // position. here is the solution: the adjustment value that is used within the position 223 // has to be updated, in case the position is a formula the first usage of a 224 // adjument value is decisive 225 if ( maAdjustHandleList[ i ].polar ) 226 { 227 aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos; 228 if ( maAdjustHandleList[ i ].min1.has() ) 229 aHandle[ PROP_RadiusRangeMinimum ] <<= maAdjustHandleList[ i ].min1.get(); 230 if ( maAdjustHandleList[ i ].max1.has() ) 231 aHandle[ PROP_RadiusRangeMaximum ] <<= maAdjustHandleList[ i ].max1.get(); 232 233 /* TODO: AngleMin & AngleMax 234 if ( maAdjustHandleList[ i ].min2.has() ) 235 aHandle[ PROP_ ] = maAdjustHandleList[ i ].min2.get(); 236 if ( maAdjustHandleList[ i ].max2.has() ) 237 aHandle[ PROP_ ] = maAdjustHandleList[ i ].max2.get(); 238 */ 239 } 240 else 241 { 242 aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos; 243 if ( maAdjustHandleList[ i ].gdRef1.has() ) 244 { 245 // TODO: PROP_RefX and PROP_RefY are not yet part of our file format, 246 // so the handles will not work after save/reload 247 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef1.get() ); 248 if ( nIndex >= 0 ) 249 aHandle[ PROP_RefX ] <<= nIndex; 250 } 251 if ( maAdjustHandleList[ i ].gdRef2.has() ) 252 { 253 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef2.get() ); 254 if ( nIndex >= 0 ) 255 aHandle[ PROP_RefY ] <<= nIndex; 256 } 257 if ( maAdjustHandleList[ i ].min1.has() ) 258 aHandle[ PROP_RangeXMinimum ] <<= maAdjustHandleList[ i ].min1.get(); 259 if ( maAdjustHandleList[ i ].max1.has() ) 260 aHandle[ PROP_RangeXMaximum ] <<= maAdjustHandleList[ i ].max1.get(); 261 if ( maAdjustHandleList[ i ].min2.has() ) 262 aHandle[ PROP_RangeYMinimum ] <<= maAdjustHandleList[ i ].min2.get(); 263 if ( maAdjustHandleList[ i ].max2.has() ) 264 aHandle[ PROP_RangeYMaximum ] <<= maAdjustHandleList[ i ].max2.get(); 265 } 266 aHandles[ i ] = aHandle.makePropertyValueSequence(); 267 } 268 aPropertyMap[ PROP_Handles ] <<= aHandles; 269 270 // converting the vector to a sequence 271 Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence(); 272 PropertySet aPropSet( xPropSet ); 273 aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq ); 274 } 275 } 276 277 double CustomShapeProperties::getValue( const std::vector< CustomShapeGuide >& rGuideList, sal_uInt32 nIndex ) const 278 { 279 double fRet = 0.0; 280 if ( nIndex < rGuideList.size() ) 281 { 282 283 } 284 return fRet; 285 } 286 287 } } 288