1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: shapeexport3.cxx,v $
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>
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" );
81 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
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
;
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
);
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
;
130 SdXMLImExTransform3D aTransform
;
131 aTransform
.AddHomogenMatrix(xHomMat
);
132 if(aTransform
.NeedsAction())
133 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_TRANSFORM
, aTransform
.GetExportString(mrExport
.GetMM100UnitConverter()));
137 case XmlShapeTypeDraw3DCubeObject
:
139 // write 3DCube shape
140 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_CUBE
, sal_True
, sal_True
);
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
);
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
;
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
);
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
);
175 case XmlShapeTypeDraw3DSphereObject
:
177 // write 3DSphere shape
178 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_SPHERE
, sal_True
, sal_True
);
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
);
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
);
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
);
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
);
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
224 sal_Int32
nOuterSequenceCount(xPolyPolygon3D
.SequenceX
.getLength());
225 drawing::DoubleSequence
* pInnerSequenceX
= xPolyPolygon3D
.SequenceX
.getArray();
226 drawing::DoubleSequence
* pInnerSequenceY
= xPolyPolygon3D
.SequenceY
.getArray();
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
++;
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
));
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
,
304 // #80594# corrected error in PolyPolygon3D export for 3D XML
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
);
319 // write 3DExtrude shape
320 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_EXTRUDE
, sal_True
, sal_True
);
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
)
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
;
342 SdXMLImExTransform3D aTransform
;
343 aTransform
.AddHomogenMatrix(xHomMat
);
344 if(aTransform
.NeedsAction())
345 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_TRANSFORM
, aTransform
.GetExportString(mrExport
.GetMM100UnitConverter()));
348 aAny
= xPropSet
->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DCameraGeometry")));
349 drawing::CameraGeometry 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
;
380 if(xPrjMode
== drawing::ProjectionMode_PARALLEL
)
381 aStr
= GetXMLToken(XML_PARALLEL
);
383 aStr
= GetXMLToken(XML_PERSPECTIVE
);
384 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_PROJECTION
, aStr
);
387 aAny
= xPropSet
->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneDistance")));
388 sal_Int32 nDistance
= 0;
390 mrExport
.GetMM100UnitConverter().convertMeasure(sStringBuffer
, nDistance
);
391 aStr
= sStringBuffer
.makeStringAndClear();
392 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_DISTANCE
, aStr
);
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
);
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
);
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
);
422 aStr
= GetXMLToken(XML_DRAFT
);
426 // ShadeMode enum not there, write default
427 aStr
= GetXMLToken(XML_GOURAUD
);
429 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SHADE_MODE
, aStr
);
432 aAny
= xPropSet
->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneAmbientColor")));
433 sal_Int32 aColTemp
= 0;
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
);
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
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") );
462 sal_Int32 aColTemp
= 0;
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
);
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
);
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
);
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
);
498 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SPECULAR
,
499 nLamp
== 1 ? XML_TRUE
: XML_FALSE
);
502 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_LIGHT
, sal_True
, sal_True
);
506 //////////////////////////////////////////////////////////////////////////////