Update ooo320-m1
[ooovba.git] / xmloff / source / draw / shapeexport3.cxx
bloba6bf644c290e74c1faa87bbfcbd21b86fe53b5b0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shapeexport3.cxx,v $
10 * $Revision: 1.23 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
33 #include <com/sun/star/drawing/HomogenMatrix.hpp>
34 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
35 #include <com/sun/star/drawing/ProjectionMode.hpp>
36 #include <com/sun/star/drawing/ShadeMode.hpp>
37 #include <com/sun/star/drawing/Direction3D.hpp>
38 #include <com/sun/star/drawing/Position3D.hpp>
39 #include <com/sun/star/drawing/CameraGeometry.hpp>
40 #include <com/sun/star/drawing/DoubleSequence.hpp>
42 #ifndef _XMLOFF_SHAPEEXPORT_HXX
43 #include <xmloff/shapeexport.hxx>
44 #endif
45 #include "sdpropls.hxx"
46 #include <tools/debug.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <xmloff/xmlexp.hxx>
49 #include <xmloff/xmluconv.hxx>
50 #include "xexptran.hxx"
51 #include <xmloff/xmltoken.hxx>
52 #include <basegfx/vector/b3dvector.hxx>
54 #include "xmlnmspe.hxx"
56 using ::rtl::OUString;
57 using ::rtl::OUStringBuffer;
59 using namespace ::com::sun::star;
60 using namespace ::xmloff::token;
62 //////////////////////////////////////////////////////////////////////////////
64 inline sal_Int32 FRound( double fVal )
66 return( fVal > 0.0 ? (sal_Int32) ( fVal + 0.5 ) : -(sal_Int32) ( -fVal + 0.5 ) );
69 //////////////////////////////////////////////////////////////////////////////
71 void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
73 uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
74 if(xShapes.is() && xShapes->getCount())
76 uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
77 DBG_ASSERT( xPropSet.is(), "XMLShapeExport::ImpExport3DSceneShape can't export a scene without a propertyset" );
78 if( xPropSet.is() )
80 // Transformation
81 ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
83 // 3d attributes
84 export3DSceneAttributes( xPropSet );
86 // write 3DScene shape
87 sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
88 SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DR3D, XML_SCENE, bCreateNewline, sal_True);
90 ImpExportDescription( xShape ); // #i68101#
91 ImpExportEvents( xShape );
93 // write 3DSceneLights
94 export3DLamps( xPropSet );
96 // #89764# if export of position is supressed for group shape,
97 // positions of contained objects should be written relative to
98 // the upper left edge of the group.
99 awt::Point aUpperLeft;
101 if(!(nFeatures & SEF_EXPORT_POSITION))
103 nFeatures |= SEF_EXPORT_POSITION;
104 aUpperLeft = xShape->getPosition();
105 pRefPoint = &aUpperLeft;
108 // write members
109 exportShapes( xShapes, nFeatures, pRefPoint );
114 //////////////////////////////////////////////////////////////////////////////
116 void XMLShapeExport::ImpExport3DShape(
117 const uno::Reference< drawing::XShape >& xShape,
118 XmlShapeType eShapeType, sal_Int32 /* nFeatures = SEF_DEFAULT */, awt::Point* /*pRefPoint = NULL */)
120 const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
121 if(xPropSet.is())
123 OUString aStr;
124 OUStringBuffer sStringBuffer;
126 // transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
127 uno::Any aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix")));
128 drawing::HomogenMatrix xHomMat;
129 aAny >>= xHomMat;
130 SdXMLImExTransform3D aTransform;
131 aTransform.AddHomogenMatrix(xHomMat);
132 if(aTransform.NeedsAction())
133 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
135 switch(eShapeType)
137 case XmlShapeTypeDraw3DCubeObject:
139 // write 3DCube shape
140 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_CUBE, sal_True, sal_True);
142 // minEdge
143 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition")));
144 drawing::Position3D aPosition3D;
145 aAny >>= aPosition3D;
146 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
148 // maxEdge
149 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize")));
150 drawing::Direction3D aDirection3D;
151 aAny >>= aDirection3D;
152 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
154 // transform maxEdge from distance to pos
155 aDir3D = aPos3D + aDir3D;
157 // write minEdge
158 if(aPos3D != ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default
160 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D);
161 aStr = sStringBuffer.makeStringAndClear();
162 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MIN_EDGE, aStr);
165 // write maxEdge
166 if(aDir3D != ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default
168 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D);
169 aStr = sStringBuffer.makeStringAndClear();
170 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MAX_EDGE, aStr);
173 break;
175 case XmlShapeTypeDraw3DSphereObject:
177 // write 3DSphere shape
178 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_SPHERE, sal_True, sal_True);
180 // Center
181 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition")));
182 drawing::Position3D aPosition3D;
183 aAny >>= aPosition3D;
184 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
186 // Size
187 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize")));
188 drawing::Direction3D aDirection3D;
189 aAny >>= aDirection3D;
190 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
192 // write Center
193 if(aPos3D != ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default
195 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D);
196 aStr = sStringBuffer.makeStringAndClear();
197 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_CENTER, aStr);
200 // write Size
201 if(aDir3D != ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default
203 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D);
204 aStr = sStringBuffer.makeStringAndClear();
205 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SIZE, aStr);
208 break;
210 case XmlShapeTypeDraw3DLatheObject:
211 case XmlShapeTypeDraw3DExtrudeObject:
213 // write special 3DLathe/3DExtrude attributes
214 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPolyPolygon3D")));
215 drawing::PolyPolygonShape3D xPolyPolygon3D;
216 aAny >>= xPolyPolygon3D;
218 // look for maximal values
219 double fXMin = 0;
220 double fXMax = 0;
221 double fYMin = 0;
222 double fYMax = 0;
223 BOOL bInit(FALSE);
224 sal_Int32 nOuterSequenceCount(xPolyPolygon3D.SequenceX.getLength());
225 drawing::DoubleSequence* pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
226 drawing::DoubleSequence* pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
228 sal_Int32 a;
229 for( a= 0L; a < nOuterSequenceCount; a++)
231 sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
232 double* pArrayX = pInnerSequenceX->getArray();
233 double* pArrayY = pInnerSequenceY->getArray();
235 for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
237 double fX = *pArrayX++;
238 double fY = *pArrayY++;
240 if(bInit)
242 if(fX > fXMax)
243 fXMax = fX;
245 if(fX < fXMin)
246 fXMin = fX;
248 if(fY > fYMax)
249 fYMax = fY;
251 if(fY < fYMin)
252 fYMin = fY;
254 else
256 fXMin = fXMax = fX;
257 fYMin = fYMax = fY;
258 bInit = TRUE;
262 pInnerSequenceX++;
263 pInnerSequenceY++;
266 // export ViewBox
267 awt::Point aMinPoint(FRound(fXMin), FRound(fYMin));
268 awt::Size aMaxSize(FRound(fXMax) - aMinPoint.X, FRound(fYMax) - aMinPoint.Y);
269 SdXMLImExViewBox aViewBox(
270 aMinPoint.X, aMinPoint.Y, aMaxSize.Width, aMaxSize.Height);
271 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
272 aViewBox.GetExportString());
274 // prepare svx:d element export
275 SdXMLImExSvgDElement aSvgDElement(aViewBox);
276 pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
277 pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
279 for(a = 0L; a < nOuterSequenceCount; a++)
281 sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
282 double* pArrayX = pInnerSequenceX->getArray();
283 double* pArrayY = pInnerSequenceY->getArray();
284 drawing::PointSequence aPoly(nInnerSequenceCount);
285 awt::Point* pInnerSequence = aPoly.getArray();
287 for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
289 double fX = *pArrayX++;
290 double fY = *pArrayY++;
292 *pInnerSequence = awt::Point(FRound(fX), FRound(fY));
293 pInnerSequence++;
296 // calculate closed flag
297 awt::Point* pFirst = aPoly.getArray();
298 awt::Point* pLast = pFirst + (nInnerSequenceCount - 1);
299 BOOL bClosed = (pFirst->X == pLast->X && pFirst->Y == pLast->Y);
301 aSvgDElement.AddPolygon(&aPoly, 0L, aMinPoint,
302 aMaxSize, bClosed);
304 // #80594# corrected error in PolyPolygon3D export for 3D XML
305 pInnerSequenceX++;
306 pInnerSequenceY++;
309 // write point array
310 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
312 if(eShapeType == XmlShapeTypeDraw3DLatheObject)
314 // write 3DLathe shape
315 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_ROTATE, sal_True, sal_True);
317 else
319 // write 3DExtrude shape
320 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_EXTRUDE, sal_True, sal_True);
322 break;
324 default:
325 break;
330 //////////////////////////////////////////////////////////////////////////////
332 /** helper for chart that adds all attributes of a 3d scene element to the export */
333 void XMLShapeExport::export3DSceneAttributes( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet )
335 OUString aStr;
336 OUStringBuffer sStringBuffer;
338 // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
339 uno::Any aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix")));
340 drawing::HomogenMatrix xHomMat;
341 aAny >>= xHomMat;
342 SdXMLImExTransform3D aTransform;
343 aTransform.AddHomogenMatrix(xHomMat);
344 if(aTransform.NeedsAction())
345 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
347 // VRP, VPN, VUP
348 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DCameraGeometry")));
349 drawing::CameraGeometry aCamGeo;
350 aAny >>= aCamGeo;
352 ::basegfx::B3DVector aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ);
353 if(aVRP != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
355 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVRP);
356 aStr = sStringBuffer.makeStringAndClear();
357 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VRP, aStr);
360 ::basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ);
361 if(aVPN != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
363 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVPN);
364 aStr = sStringBuffer.makeStringAndClear();
365 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VPN, aStr);
368 ::basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ);
369 if(aVUP != ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default
371 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVUP);
372 aStr = sStringBuffer.makeStringAndClear();
373 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VUP, aStr);
376 // projection "D3DScenePerspective" drawing::ProjectionMode
377 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DScenePerspective")));
378 drawing::ProjectionMode xPrjMode;
379 aAny >>= xPrjMode;
380 if(xPrjMode == drawing::ProjectionMode_PARALLEL)
381 aStr = GetXMLToken(XML_PARALLEL);
382 else
383 aStr = GetXMLToken(XML_PERSPECTIVE);
384 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_PROJECTION, aStr);
386 // distance
387 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneDistance")));
388 sal_Int32 nDistance = 0;
389 aAny >>= nDistance;
390 mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDistance);
391 aStr = sStringBuffer.makeStringAndClear();
392 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DISTANCE, aStr);
394 // focalLength
395 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneFocalLength")));
396 sal_Int32 nFocalLength = 0;
397 aAny >>= nFocalLength;
398 mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nFocalLength);
399 aStr = sStringBuffer.makeStringAndClear();
400 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_FOCAL_LENGTH, aStr);
402 // shadowSlant
403 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadowSlant")));
404 sal_Int16 nShadowSlant = 0;
405 aAny >>= nShadowSlant;
406 mrExport.GetMM100UnitConverter().convertNumber(sStringBuffer, (sal_Int32)nShadowSlant);
407 aStr = sStringBuffer.makeStringAndClear();
408 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADOW_SLANT, aStr);
410 // shadeMode
411 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadeMode")));
412 drawing::ShadeMode xShadeMode;
413 if(aAny >>= xShadeMode)
415 if(xShadeMode == drawing::ShadeMode_FLAT)
416 aStr = GetXMLToken(XML_FLAT);
417 else if(xShadeMode == drawing::ShadeMode_PHONG)
418 aStr = GetXMLToken(XML_PHONG);
419 else if(xShadeMode == drawing::ShadeMode_SMOOTH)
420 aStr = GetXMLToken(XML_GOURAUD);
421 else
422 aStr = GetXMLToken(XML_DRAFT);
424 else
426 // ShadeMode enum not there, write default
427 aStr = GetXMLToken(XML_GOURAUD);
429 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADE_MODE, aStr);
431 // ambientColor
432 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneAmbientColor")));
433 sal_Int32 aColTemp = 0;
434 Color aAmbientColor;
435 aAny >>= aColTemp; aAmbientColor.SetColor(aColTemp);
436 mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aAmbientColor);
437 aStr = sStringBuffer.makeStringAndClear();
438 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_AMBIENT_COLOR, aStr);
440 // lightingMode
441 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneTwoSidedLighting")));
442 sal_Bool bTwoSidedLighting = false;
443 aAny >>= bTwoSidedLighting;
444 mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bTwoSidedLighting);
445 aStr = sStringBuffer.makeStringAndClear();
446 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_LIGHTING_MODE, aStr);
449 /** helper for chart that exports all lamps from the propertyset */
450 void XMLShapeExport::export3DLamps( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet )
452 // write lamps 1..8 as content
453 OUString aStr;
454 OUStringBuffer sStringBuffer;
456 const OUString aColorPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor") );
457 const OUString aDirectionPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection") );
458 const OUString aLightOnPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn") );
460 OUString aPropName;
461 OUString aIndexStr;
462 sal_Int32 aColTemp = 0;
463 Color aLightColor;
464 ::basegfx::B3DVector aLightDirection;
465 drawing::Direction3D xLightDir;
466 sal_Bool bLightOnOff = false;
467 for(sal_Int32 nLamp = 1; nLamp <= 8; nLamp++)
469 aIndexStr = OUString::valueOf( nLamp );
471 // lightcolor
472 aPropName = aColorPropName;
473 aPropName += aIndexStr;
474 xPropSet->getPropertyValue( aPropName ) >>= aColTemp;
475 aLightColor.SetColor(aColTemp);
476 mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aLightColor);
477 aStr = sStringBuffer.makeStringAndClear();
478 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIFFUSE_COLOR, aStr);
480 // lightdirection
481 aPropName = aDirectionPropName;
482 aPropName += aIndexStr;
483 xPropSet->getPropertyValue(aPropName) >>= xLightDir;
484 aLightDirection = ::basegfx::B3DVector(xLightDir.DirectionX, xLightDir.DirectionY, xLightDir.DirectionZ);
485 mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aLightDirection);
486 aStr = sStringBuffer.makeStringAndClear();
487 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIRECTION, aStr);
489 // lighton
490 aPropName = aLightOnPropName;
491 aPropName += aIndexStr;
492 xPropSet->getPropertyValue(aPropName) >>= bLightOnOff;
493 mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bLightOnOff);
494 aStr = sStringBuffer.makeStringAndClear();
495 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_ENABLED, aStr);
497 // specular
498 mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SPECULAR,
499 nLamp == 1 ? XML_TRUE : XML_FALSE);
501 // write light entry
502 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_LIGHT, sal_True, sal_True);
506 //////////////////////////////////////////////////////////////////////////////