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