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 { 49 } 50 CustomShapeProperties::~CustomShapeProperties() 51 { 52 } 53 54 sal_Int32 CustomShapeProperties::SetCustomShapeGuideValue( std::vector< CustomShapeGuide >& rGuideList, const CustomShapeGuide& rGuide ) 55 { 56 sal_uInt32 nIndex = 0; 57 for( ; nIndex < rGuideList.size(); nIndex++ ) 58 { 59 if ( rGuideList[ nIndex ].maName == rGuide.maName ) 60 break; 61 } 62 if ( nIndex == rGuideList.size() ) 63 rGuideList.push_back( rGuide ); 64 return static_cast< sal_Int32 >( nIndex ); 65 } 66 67 // returns the index into the guidelist for a given formula name, 68 // if the return value is < 0 then the guide value could not be found 69 sal_Int32 CustomShapeProperties::GetCustomShapeGuideValue( const std::vector< CustomShapeGuide >& rGuideList, const rtl::OUString& rFormulaName ) 70 { 71 sal_Int32 nIndex = 0; 72 for( ; nIndex < static_cast< sal_Int32 >( rGuideList.size() ); nIndex++ ) 73 { 74 if ( rGuideList[ nIndex ].maName == rFormulaName ) 75 break; 76 } 77 if ( nIndex == static_cast< sal_Int32 >( rGuideList.size() ) ) 78 nIndex = -1; 79 return nIndex; 80 } 81 82 void CustomShapeProperties::apply( const CustomShapePropertiesPtr& /* rSourceCustomShapeProperties */ ) 83 { 84 // not sure if this needs to be implemented 85 } 86 87 void CustomShapeProperties::pushToPropSet( const ::oox::core::FilterBase& /* rFilterBase */, 88 const Reference < XPropertySet >& xPropSet, const Reference < XShape > & xShape ) const 89 { 90 if ( maShapePresetType.getLength() ) 91 { 92 //const uno::Reference < drawing::XShape > xShape( xPropSet, UNO_QUERY ); 93 Reference< drawing::XEnhancedCustomShapeDefaulter > xDefaulter( xShape, UNO_QUERY ); 94 if( xDefaulter.is() ) 95 xDefaulter->createCustomShapeDefaults( maShapePresetType ); 96 97 if ( maAdjustmentGuideList.size() ) 98 { 99 const OUString sType = CREATE_OUSTRING( "Type" ); 100 const OUString sCustomShapeGeometry( RTL_CONSTASCII_USTRINGPARAM( "CustomShapeGeometry" ) ); 101 uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry ); 102 uno::Sequence< beans::PropertyValue > aGeoPropSeq; 103 if ( aGeoPropSet >>= aGeoPropSeq ) 104 { 105 sal_Int32 i, nCount = aGeoPropSeq.getLength(); 106 for ( i = 0; i < nCount; i++ ) 107 { 108 const rtl::OUString sAdjustmentValues( RTL_CONSTASCII_USTRINGPARAM( "AdjustmentValues" ) ); 109 if ( aGeoPropSeq[ i ].Name.equals( sAdjustmentValues ) ) 110 { 111 uno::Sequence< com::sun::star::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq; 112 if ( aGeoPropSeq[ i ].Value >>= aAdjustmentSeq ) 113 { 114 std::vector< CustomShapeGuide >::const_iterator aIter( maAdjustmentGuideList.begin() ); 115 while( aIter != maAdjustmentGuideList.end() ) 116 { 117 if ( (*aIter).maName.getLength() > 3 ) 118 { 119 sal_Int32 nAdjustmentIndex = (*aIter).maName.copy( 3 ).toInt32() - 1; 120 if ( ( nAdjustmentIndex >= 0 ) && ( nAdjustmentIndex < aAdjustmentSeq.getLength() ) ) 121 { 122 EnhancedCustomShapeAdjustmentValue aAdjustmentVal; 123 aAdjustmentVal.Value <<= (*aIter).maFormula.toInt32(); 124 aAdjustmentVal.State = PropertyState_DIRECT_VALUE; 125 aAdjustmentSeq[ nAdjustmentIndex ] = aAdjustmentVal; 126 } 127 } 128 aIter++; 129 } 130 aGeoPropSeq[ i ].Value <<= aAdjustmentSeq; 131 xPropSet->setPropertyValue( sCustomShapeGeometry, Any( aGeoPropSeq ) ); 132 } 133 } 134 else if ( aGeoPropSeq[ i ].Name.equals( sType ) ) 135 { 136 aGeoPropSeq[ i ].Value <<= maShapePresetType; 137 } 138 } 139 } 140 } 141 } 142 else 143 { 144 sal_uInt32 i; 145 PropertyMap aPropertyMap; 146 aPropertyMap[ PROP_Type ] <<= CREATE_OUSTRING( "non-primitive" ); 147 aPropertyMap[ PROP_MirroredX ] <<= Any( mbMirroredX ); 148 aPropertyMap[ PROP_MirroredY ] <<= Any( mbMirroredY ); 149 awt::Size aSize( xShape->getSize() ); 150 awt::Rectangle aViewBox( 0, 0, aSize.Width * 360, aSize.Height * 360 ); 151 if ( maPath2DList.size() ) 152 { // TODO: each polygon may have its own size, but I think it is rather been used 153 // so we are only taking care of the first 154 if ( maPath2DList[ 0 ].w ) 155 aViewBox.Width = static_cast< sal_Int32 >( maPath2DList[ 0 ].w ); 156 if ( maPath2DList[ 0 ].h ) 157 aViewBox.Height = static_cast< sal_Int32 >( maPath2DList[ 0 ].h ); 158 } 159 aPropertyMap[ PROP_ViewBox ] <<= aViewBox; 160 161 Sequence< EnhancedCustomShapeAdjustmentValue > aAdjustmentValues( maAdjustmentGuideList.size() ); 162 for ( i = 0; i < maAdjustmentGuideList.size(); i++ ) 163 { 164 EnhancedCustomShapeAdjustmentValue aAdjustmentVal; 165 aAdjustmentVal.Value <<= maAdjustmentGuideList[ i ].maFormula.toInt32(); 166 aAdjustmentVal.State = PropertyState_DIRECT_VALUE; 167 aAdjustmentValues[ i ] = aAdjustmentVal; 168 } 169 aPropertyMap[ PROP_AdjustmentValues ] <<= aAdjustmentValues; 170 171 Sequence< rtl::OUString > aEquations( maGuideList.size() ); 172 for ( i = 0; i < maGuideList.size(); i++ ) 173 aEquations[ i ] = maGuideList[ i ].maFormula; 174 aPropertyMap[ PROP_Equations ] <<= aEquations; 175 176 PropertyMap aPath; 177 Sequence< EnhancedCustomShapeSegment > aSegments( maSegments.size() ); 178 for ( i = 0; i < maSegments.size(); i++ ) 179 aSegments[ i ] = maSegments[ i ]; 180 aPath[ PROP_Segments ] <<= aSegments; 181 sal_uInt32 j, k, nParameterPairs = 0; 182 for ( i = 0; i < maPath2DList.size(); i++ ) 183 nParameterPairs += maPath2DList[ i ].parameter.size(); 184 Sequence< EnhancedCustomShapeParameterPair > aParameterPairs( nParameterPairs ); 185 for ( i = 0, k = 0; i < maPath2DList.size(); i++ ) 186 for ( j = 0; j < maPath2DList[ i ].parameter.size(); j++ ) 187 aParameterPairs[ k++ ] = maPath2DList[ i ].parameter[ j ]; 188 aPath[ PROP_Coordinates ] <<= aParameterPairs; 189 Sequence< PropertyValue > aPathSequence = aPath.makePropertyValueSequence(); 190 aPropertyMap[ PROP_Path ] <<= aPathSequence; 191 192 Sequence< PropertyValues > aHandles( maAdjustHandleList.size() ); 193 for ( i = 0; i < maAdjustHandleList.size(); i++ ) 194 { 195 PropertyMap aHandle; 196 // maAdjustmentHandle[ i ].gdRef1 ... maAdjustmentHandle[ i ].gdRef2 ... :( 197 // gdRef1 && gdRef2 -> we do not offer such reference, so it is difficult 198 // to determine the correct adjustment handle that should be updated with the adjustment 199 // position. here is the solution: the adjustment value that is used within the position 200 // has to be updated, in case the position is a formula the first usage of a 201 // adjument value is decisive 202 if ( maAdjustHandleList[ i ].polar ) 203 { 204 aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos; 205 if ( maAdjustHandleList[ i ].min1.has() ) 206 aHandle[ PROP_RadiusRangeMinimum ] <<= maAdjustHandleList[ i ].min1.get(); 207 if ( maAdjustHandleList[ i ].max1.has() ) 208 aHandle[ PROP_RadiusRangeMaximum ] <<= maAdjustHandleList[ i ].max1.get(); 209 210 /* TODO: AngleMin & AngleMax 211 if ( maAdjustHandleList[ i ].min2.has() ) 212 aHandle[ PROP_ ] = maAdjustHandleList[ i ].min2.get(); 213 if ( maAdjustHandleList[ i ].max2.has() ) 214 aHandle[ PROP_ ] = maAdjustHandleList[ i ].max2.get(); 215 */ 216 } 217 else 218 { 219 aHandle[ PROP_Position ] <<= maAdjustHandleList[ i ].pos; 220 if ( maAdjustHandleList[ i ].gdRef1.has() ) 221 { 222 // TODO: PROP_RefX and PROP_RefY are not yet part of our file format, 223 // so the handles will not work after save/reload 224 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef1.get() ); 225 if ( nIndex >= 0 ) 226 aHandle[ PROP_RefX ] <<= nIndex; 227 } 228 if ( maAdjustHandleList[ i ].gdRef2.has() ) 229 { 230 sal_Int32 nIndex = GetCustomShapeGuideValue( maAdjustmentGuideList, maAdjustHandleList[ i ].gdRef2.get() ); 231 if ( nIndex >= 0 ) 232 aHandle[ PROP_RefY ] <<= nIndex; 233 } 234 if ( maAdjustHandleList[ i ].min1.has() ) 235 aHandle[ PROP_RangeXMinimum ] <<= maAdjustHandleList[ i ].min1.get(); 236 if ( maAdjustHandleList[ i ].max1.has() ) 237 aHandle[ PROP_RangeXMaximum ] <<= maAdjustHandleList[ i ].max1.get(); 238 if ( maAdjustHandleList[ i ].min2.has() ) 239 aHandle[ PROP_RangeYMinimum ] <<= maAdjustHandleList[ i ].min2.get(); 240 if ( maAdjustHandleList[ i ].max2.has() ) 241 aHandle[ PROP_RangeYMaximum ] <<= maAdjustHandleList[ i ].max2.get(); 242 } 243 aHandles[ i ] = aHandle.makePropertyValueSequence(); 244 } 245 aPropertyMap[ PROP_Handles ] <<= aHandles; 246 247 // converting the vector to a sequence 248 Sequence< PropertyValue > aSeq = aPropertyMap.makePropertyValueSequence(); 249 PropertySet aPropSet( xPropSet ); 250 aPropSet.setProperty( PROP_CustomShapeGeometry, aSeq ); 251 } 252 } 253 254 double CustomShapeProperties::getValue( const std::vector< CustomShapeGuide >& rGuideList, sal_uInt32 nIndex ) const 255 { 256 double fRet = 0.0; 257 if ( nIndex < rGuideList.size() ) 258 { 259 260 } 261 return fRet; 262 } 263 264 } } 265