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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_xmloff.hxx" 24 25 #include <com/sun/star/drawing/HomogenMatrix.hpp> 26 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp> 27 #include <com/sun/star/drawing/ProjectionMode.hpp> 28 #include <com/sun/star/drawing/ShadeMode.hpp> 29 #include <com/sun/star/drawing/Direction3D.hpp> 30 #include <com/sun/star/drawing/Position3D.hpp> 31 #include <com/sun/star/drawing/CameraGeometry.hpp> 32 #include <com/sun/star/drawing/DoubleSequence.hpp> 33 #include <tools/gen.hxx> 34 #include <xmloff/shapeexport.hxx> 35 #include "sdpropls.hxx" 36 #include <tools/debug.hxx> 37 #include <rtl/ustrbuf.hxx> 38 #include <xmloff/xmlexp.hxx> 39 #include <xmloff/xmluconv.hxx> 40 #include "xexptran.hxx" 41 #include <xmloff/xmltoken.hxx> 42 #include <basegfx/vector/b3dvector.hxx> 43 #include <xmloff/xmlnmspe.hxx> 44 #include <basegfx/polygon/b3dpolypolygon.hxx> 45 #include <basegfx/polygon/b3dpolypolygontools.hxx> 46 #include <basegfx/matrix/b3dhommatrix.hxx> 47 #include <basegfx/polygon/b2dpolypolygon.hxx> 48 #include <basegfx/polygon/b2dpolypolygontools.hxx> 49 50 using ::rtl::OUString; 51 using ::rtl::OUStringBuffer; 52 53 using namespace ::com::sun::star; 54 using namespace ::xmloff::token; 55 56 57 ////////////////////////////////////////////////////////////////////////////// 58 59 void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint) 60 { 61 uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY); 62 if(xShapes.is() && xShapes->getCount()) 63 { 64 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY ); 65 DBG_ASSERT( xPropSet.is(), "XMLShapeExport::ImpExport3DSceneShape can't export a scene without a propertyset" ); 66 if( xPropSet.is() ) 67 { 68 // Transformation 69 ImpExportNewTrans(xPropSet, nFeatures, pRefPoint); 70 71 // 3d attributes 72 export3DSceneAttributes( xPropSet ); 73 74 // write 3DScene shape 75 sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210# 76 SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DR3D, XML_SCENE, bCreateNewline, sal_True); 77 78 ImpExportDescription( xShape ); // #i68101# 79 ImpExportEvents( xShape ); 80 81 // write 3DSceneLights 82 export3DLamps( xPropSet ); 83 84 // #89764# if export of position is supressed for group shape, 85 // positions of contained objects should be written relative to 86 // the upper left edge of the group. 87 awt::Point aUpperLeft; 88 89 if(!(nFeatures & SEF_EXPORT_POSITION)) 90 { 91 nFeatures |= SEF_EXPORT_POSITION; 92 aUpperLeft = xShape->getPosition(); 93 pRefPoint = &aUpperLeft; 94 } 95 96 // write members 97 exportShapes( xShapes, nFeatures, pRefPoint ); 98 } 99 } 100 } 101 102 ////////////////////////////////////////////////////////////////////////////// 103 104 void XMLShapeExport::ImpExport3DShape( 105 const uno::Reference< drawing::XShape >& xShape, 106 XmlShapeType eShapeType, sal_Int32 /* nFeatures = SEF_DEFAULT */, awt::Point* /*pRefPoint = NULL */) 107 { 108 const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY); 109 if(xPropSet.is()) 110 { 111 OUString aStr; 112 OUStringBuffer sStringBuffer; 113 114 // transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix") 115 uno::Any aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix"))); 116 drawing::HomogenMatrix xHomMat; 117 aAny >>= xHomMat; 118 SdXMLImExTransform3D aTransform; 119 aTransform.AddHomogenMatrix(xHomMat); 120 if(aTransform.NeedsAction()) 121 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter())); 122 123 switch(eShapeType) 124 { 125 case XmlShapeTypeDraw3DCubeObject: 126 { 127 // minEdge 128 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition"))); 129 drawing::Position3D aPosition3D; 130 aAny >>= aPosition3D; 131 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ); 132 133 // maxEdge 134 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize"))); 135 drawing::Direction3D aDirection3D; 136 aAny >>= aDirection3D; 137 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ); 138 139 // transform maxEdge from distance to pos 140 aDir3D = aPos3D + aDir3D; 141 142 // write minEdge 143 if(aPos3D != ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default 144 { 145 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D); 146 aStr = sStringBuffer.makeStringAndClear(); 147 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MIN_EDGE, aStr); 148 } 149 150 // write maxEdge 151 if(aDir3D != ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default 152 { 153 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D); 154 aStr = sStringBuffer.makeStringAndClear(); 155 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MAX_EDGE, aStr); 156 } 157 158 // write 3DCube shape 159 // #123542# Do this *after* the attributes are added, else these will be lost since opening 160 // the scope will clear the global attribute list at the exporter 161 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_CUBE, sal_True, sal_True); 162 163 break; 164 } 165 case XmlShapeTypeDraw3DSphereObject: 166 { 167 // Center 168 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition"))); 169 drawing::Position3D aPosition3D; 170 aAny >>= aPosition3D; 171 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ); 172 173 // Size 174 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize"))); 175 drawing::Direction3D aDirection3D; 176 aAny >>= aDirection3D; 177 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ); 178 179 // write Center 180 if(aPos3D != ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default 181 { 182 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D); 183 aStr = sStringBuffer.makeStringAndClear(); 184 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_CENTER, aStr); 185 } 186 187 // write Size 188 if(aDir3D != ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default 189 { 190 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D); 191 aStr = sStringBuffer.makeStringAndClear(); 192 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SIZE, aStr); 193 } 194 195 // write 3DSphere shape 196 // #123542# Do this *after* the attributes are added, else these will be lost since opening 197 // the scope will clear the global attribute list at the exporter 198 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_SPHERE, sal_True, sal_True); 199 200 break; 201 } 202 case XmlShapeTypeDraw3DLatheObject: 203 case XmlShapeTypeDraw3DExtrudeObject: 204 { 205 // write special 3DLathe/3DExtrude attributes, get 3D PolyPolygon as drawing::PolyPolygonShape3D 206 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPolyPolygon3D"))); 207 drawing::PolyPolygonShape3D xPolyPolygon3D; 208 aAny >>= xPolyPolygon3D; 209 210 // convert to 3D PolyPolygon 211 const basegfx::B3DPolyPolygon aPolyPolygon3D( 212 basegfx::tools::UnoPolyPolygonShape3DToB3DPolyPolygon( 213 xPolyPolygon3D)); 214 215 // convert to 2D PolyPolygon using identity 3D transformation (just grep X and Y) 216 const basegfx::B3DHomMatrix aB3DHomMatrixFor2DConversion; 217 const basegfx::B2DPolyPolygon aPolyPolygon( 218 basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon( 219 aPolyPolygon3D, 220 aB3DHomMatrixFor2DConversion)); 221 222 // get 2D range of it 223 const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange()); 224 225 // export ViewBox 226 SdXMLImExViewBox aViewBox( 227 aPolyPolygonRange.getMinX(), 228 aPolyPolygonRange.getMinY(), 229 aPolyPolygonRange.getWidth(), 230 aPolyPolygonRange.getHeight()); 231 232 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString()); 233 234 // prepare svg:d string 235 const ::rtl::OUString aPolygonString( 236 basegfx::tools::exportToSvgD( 237 aPolyPolygon, 238 true, // bUseRelativeCoordinates 239 false, // bDetectQuadraticBeziers TTTT: not used in old, but maybe activated now 240 true)); // bHandleRelativeNextPointCompatible 241 242 // write point array 243 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString); 244 245 if(eShapeType == XmlShapeTypeDraw3DLatheObject) 246 { 247 // write 3DLathe shape 248 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_ROTATE, sal_True, sal_True); 249 } 250 else 251 { 252 // write 3DExtrude shape 253 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_EXTRUDE, sal_True, sal_True); 254 } 255 break; 256 } 257 default: 258 break; 259 } 260 } 261 } 262 263 ////////////////////////////////////////////////////////////////////////////// 264 265 /** helper for chart that adds all attributes of a 3d scene element to the export */ 266 void XMLShapeExport::export3DSceneAttributes( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet ) 267 { 268 OUString aStr; 269 OUStringBuffer sStringBuffer; 270 271 // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix") 272 uno::Any aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix"))); 273 drawing::HomogenMatrix xHomMat; 274 aAny >>= xHomMat; 275 SdXMLImExTransform3D aTransform; 276 aTransform.AddHomogenMatrix(xHomMat); 277 if(aTransform.NeedsAction()) 278 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter())); 279 280 // VRP, VPN, VUP 281 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DCameraGeometry"))); 282 drawing::CameraGeometry aCamGeo; 283 aAny >>= aCamGeo; 284 285 ::basegfx::B3DVector aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ); 286 if(aVRP != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default 287 { 288 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVRP); 289 aStr = sStringBuffer.makeStringAndClear(); 290 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VRP, aStr); 291 } 292 293 ::basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ); 294 if(aVPN != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default 295 { 296 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVPN); 297 aStr = sStringBuffer.makeStringAndClear(); 298 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VPN, aStr); 299 } 300 301 ::basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ); 302 if(aVUP != ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default 303 { 304 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVUP); 305 aStr = sStringBuffer.makeStringAndClear(); 306 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VUP, aStr); 307 } 308 309 // projection "D3DScenePerspective" drawing::ProjectionMode 310 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DScenePerspective"))); 311 drawing::ProjectionMode xPrjMode; 312 aAny >>= xPrjMode; 313 if(xPrjMode == drawing::ProjectionMode_PARALLEL) 314 aStr = GetXMLToken(XML_PARALLEL); 315 else 316 aStr = GetXMLToken(XML_PERSPECTIVE); 317 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_PROJECTION, aStr); 318 319 // distance 320 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneDistance"))); 321 sal_Int32 nDistance = 0; 322 aAny >>= nDistance; 323 mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDistance); 324 aStr = sStringBuffer.makeStringAndClear(); 325 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DISTANCE, aStr); 326 327 // focalLength 328 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneFocalLength"))); 329 sal_Int32 nFocalLength = 0; 330 aAny >>= nFocalLength; 331 mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nFocalLength); 332 aStr = sStringBuffer.makeStringAndClear(); 333 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_FOCAL_LENGTH, aStr); 334 335 // shadowSlant 336 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadowSlant"))); 337 sal_Int16 nShadowSlant = 0; 338 aAny >>= nShadowSlant; 339 mrExport.GetMM100UnitConverter().convertNumber(sStringBuffer, (sal_Int32)nShadowSlant); 340 aStr = sStringBuffer.makeStringAndClear(); 341 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADOW_SLANT, aStr); 342 343 // shadeMode 344 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadeMode"))); 345 drawing::ShadeMode xShadeMode; 346 if(aAny >>= xShadeMode) 347 { 348 if(xShadeMode == drawing::ShadeMode_FLAT) 349 aStr = GetXMLToken(XML_FLAT); 350 else if(xShadeMode == drawing::ShadeMode_PHONG) 351 aStr = GetXMLToken(XML_PHONG); 352 else if(xShadeMode == drawing::ShadeMode_SMOOTH) 353 aStr = GetXMLToken(XML_GOURAUD); 354 else 355 aStr = GetXMLToken(XML_DRAFT); 356 } 357 else 358 { 359 // ShadeMode enum not there, write default 360 aStr = GetXMLToken(XML_GOURAUD); 361 } 362 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADE_MODE, aStr); 363 364 // ambientColor 365 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneAmbientColor"))); 366 sal_Int32 aColTemp = 0; 367 Color aAmbientColor; 368 aAny >>= aColTemp; aAmbientColor.SetColor(aColTemp); 369 mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aAmbientColor); 370 aStr = sStringBuffer.makeStringAndClear(); 371 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_AMBIENT_COLOR, aStr); 372 373 // lightingMode 374 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneTwoSidedLighting"))); 375 sal_Bool bTwoSidedLighting = false; 376 aAny >>= bTwoSidedLighting; 377 mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bTwoSidedLighting); 378 aStr = sStringBuffer.makeStringAndClear(); 379 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_LIGHTING_MODE, aStr); 380 } 381 382 /** helper for chart that exports all lamps from the propertyset */ 383 void XMLShapeExport::export3DLamps( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet ) 384 { 385 // write lamps 1..8 as content 386 OUString aStr; 387 OUStringBuffer sStringBuffer; 388 389 const OUString aColorPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor") ); 390 const OUString aDirectionPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection") ); 391 const OUString aLightOnPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn") ); 392 393 OUString aPropName; 394 OUString aIndexStr; 395 sal_Int32 aColTemp = 0; 396 Color aLightColor; 397 ::basegfx::B3DVector aLightDirection; 398 drawing::Direction3D xLightDir; 399 sal_Bool bLightOnOff = false; 400 for(sal_Int32 nLamp = 1; nLamp <= 8; nLamp++) 401 { 402 aIndexStr = OUString::valueOf( nLamp ); 403 404 // lightcolor 405 aPropName = aColorPropName; 406 aPropName += aIndexStr; 407 xPropSet->getPropertyValue( aPropName ) >>= aColTemp; 408 aLightColor.SetColor(aColTemp); 409 mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aLightColor); 410 aStr = sStringBuffer.makeStringAndClear(); 411 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIFFUSE_COLOR, aStr); 412 413 // lightdirection 414 aPropName = aDirectionPropName; 415 aPropName += aIndexStr; 416 xPropSet->getPropertyValue(aPropName) >>= xLightDir; 417 aLightDirection = ::basegfx::B3DVector(xLightDir.DirectionX, xLightDir.DirectionY, xLightDir.DirectionZ); 418 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aLightDirection); 419 aStr = sStringBuffer.makeStringAndClear(); 420 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIRECTION, aStr); 421 422 // lighton 423 aPropName = aLightOnPropName; 424 aPropName += aIndexStr; 425 xPropSet->getPropertyValue(aPropName) >>= bLightOnOff; 426 mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bLightOnOff); 427 aStr = sStringBuffer.makeStringAndClear(); 428 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_ENABLED, aStr); 429 430 // specular 431 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SPECULAR, 432 nLamp == 1 ? XML_TRUE : XML_FALSE); 433 434 // write light entry 435 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_LIGHT, sal_True, sal_True); 436 } 437 } 438 439 ////////////////////////////////////////////////////////////////////////////// 440