xref: /AOO41X/main/xmloff/source/draw/shapeexport3.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include <com/sun/star/drawing/HomogenMatrix.hpp>
27 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
28 #include <com/sun/star/drawing/ProjectionMode.hpp>
29 #include <com/sun/star/drawing/ShadeMode.hpp>
30 #include <com/sun/star/drawing/Direction3D.hpp>
31 #include <com/sun/star/drawing/Position3D.hpp>
32 #include <com/sun/star/drawing/CameraGeometry.hpp>
33 #include <com/sun/star/drawing/DoubleSequence.hpp>
34 #include <tools/gen.hxx>
35 
36 #ifndef _XMLOFF_SHAPEEXPORT_HXX
37 #include <xmloff/shapeexport.hxx>
38 #endif
39 #include "sdpropls.hxx"
40 #include <tools/debug.hxx>
41 #include <rtl/ustrbuf.hxx>
42 #include <xmloff/xmlexp.hxx>
43 #include <xmloff/xmluconv.hxx>
44 #include "xexptran.hxx"
45 #include <xmloff/xmltoken.hxx>
46 #include <basegfx/vector/b3dvector.hxx>
47 
48 #include "xmloff/xmlnmspe.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                 // write 3DCube shape
128                 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_CUBE, sal_True, sal_True);
129 
130                 // minEdge
131                 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition")));
132                 drawing::Position3D aPosition3D;
133                 aAny >>= aPosition3D;
134                 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
135 
136                 // maxEdge
137                 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize")));
138                 drawing::Direction3D aDirection3D;
139                 aAny >>= aDirection3D;
140                 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
141 
142                 // transform maxEdge from distance to pos
143                 aDir3D = aPos3D + aDir3D;
144 
145                 // write minEdge
146                 if(aPos3D != ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default
147                 {
148                     mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D);
149                     aStr = sStringBuffer.makeStringAndClear();
150                     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MIN_EDGE, aStr);
151                 }
152 
153                 // write maxEdge
154                 if(aDir3D != ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default
155                 {
156                     mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D);
157                     aStr = sStringBuffer.makeStringAndClear();
158                     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_MAX_EDGE, aStr);
159                 }
160 
161                 break;
162             }
163             case XmlShapeTypeDraw3DSphereObject:
164             {
165                 // write 3DSphere shape
166                 SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_SPHERE, sal_True, sal_True);
167 
168                 // Center
169                 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPosition")));
170                 drawing::Position3D aPosition3D;
171                 aAny >>= aPosition3D;
172                 ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
173 
174                 // Size
175                 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSize")));
176                 drawing::Direction3D aDirection3D;
177                 aAny >>= aDirection3D;
178                 ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
179 
180                 // write Center
181                 if(aPos3D != ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default
182                 {
183                     mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aPos3D);
184                     aStr = sStringBuffer.makeStringAndClear();
185                     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_CENTER, aStr);
186                 }
187 
188                 // write Size
189                 if(aDir3D != ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default
190                 {
191                     mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aDir3D);
192                     aStr = sStringBuffer.makeStringAndClear();
193                     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SIZE, aStr);
194                 }
195 
196                 break;
197             }
198             case XmlShapeTypeDraw3DLatheObject:
199             case XmlShapeTypeDraw3DExtrudeObject:
200             {
201                 // write special 3DLathe/3DExtrude attributes
202                 aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DPolyPolygon3D")));
203                 drawing::PolyPolygonShape3D xPolyPolygon3D;
204                 aAny >>= xPolyPolygon3D;
205 
206                 // look for maximal values
207                 double fXMin = 0;
208                 double fXMax = 0;
209                 double fYMin = 0;
210                 double fYMax = 0;
211                 sal_Bool bInit(sal_False);
212                 sal_Int32 nOuterSequenceCount(xPolyPolygon3D.SequenceX.getLength());
213                 drawing::DoubleSequence* pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
214                 drawing::DoubleSequence* pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
215 
216                 sal_Int32 a;
217                 for (a = 0; a < nOuterSequenceCount; a++)
218                 {
219                     sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
220                     double* pArrayX = pInnerSequenceX->getArray();
221                     double* pArrayY = pInnerSequenceY->getArray();
222 
223                     for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
224                     {
225                         double fX = *pArrayX++;
226                         double fY = *pArrayY++;
227 
228                         if(bInit)
229                         {
230                             if(fX > fXMax)
231                                 fXMax = fX;
232 
233                             if(fX < fXMin)
234                                 fXMin = fX;
235 
236                             if(fY > fYMax)
237                                 fYMax = fY;
238 
239                             if(fY < fYMin)
240                                 fYMin = fY;
241                         }
242                         else
243                         {
244                             fXMin = fXMax = fX;
245                             fYMin = fYMax = fY;
246                             bInit = sal_True;
247                         }
248                     }
249 
250                     pInnerSequenceX++;
251                     pInnerSequenceY++;
252                 }
253 
254                 // export ViewBox
255                 awt::Point aMinPoint(FRound(fXMin), FRound(fYMin));
256                 awt::Size aMaxSize(FRound(fXMax) - aMinPoint.X, FRound(fYMax) - aMinPoint.Y);
257                 SdXMLImExViewBox aViewBox(
258                     aMinPoint.X, aMinPoint.Y, aMaxSize.Width, aMaxSize.Height);
259                 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
260                     aViewBox.GetExportString());
261 
262                 // prepare svx:d element export
263                 SdXMLImExSvgDElement aSvgDElement(aViewBox);
264                 pInnerSequenceX = xPolyPolygon3D.SequenceX.getArray();
265                 pInnerSequenceY = xPolyPolygon3D.SequenceY.getArray();
266 
267                 for (a = 0; a < nOuterSequenceCount; a++)
268                 {
269                     sal_Int32 nInnerSequenceCount(pInnerSequenceX->getLength());
270                     double* pArrayX = pInnerSequenceX->getArray();
271                     double* pArrayY = pInnerSequenceY->getArray();
272                     drawing::PointSequence aPoly(nInnerSequenceCount);
273                     awt::Point* pInnerSequence = aPoly.getArray();
274 
275                     for(sal_Int32 b(0L); b < nInnerSequenceCount; b++)
276                     {
277                         double fX = *pArrayX++;
278                         double fY = *pArrayY++;
279 
280                         *pInnerSequence = awt::Point(FRound(fX), FRound(fY));
281                         pInnerSequence++;
282                     }
283 
284                     // calculate closed flag
285                     awt::Point* pFirst = aPoly.getArray();
286                     awt::Point* pLast = pFirst + (nInnerSequenceCount - 1);
287                     sal_Bool bClosed = (pFirst->X == pLast->X && pFirst->Y == pLast->Y);
288 
289                     aSvgDElement.AddPolygon(&aPoly, 0L, aMinPoint,
290                         aMaxSize, bClosed);
291 
292                     // #80594# corrected error in PolyPolygon3D export for 3D XML
293                     pInnerSequenceX++;
294                     pInnerSequenceY++;
295                 }
296 
297                 // write point array
298                 mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aSvgDElement.GetExportString());
299 
300                 if(eShapeType == XmlShapeTypeDraw3DLatheObject)
301                 {
302                     // write 3DLathe shape
303                     SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_ROTATE, sal_True, sal_True);
304                 }
305                 else
306                 {
307                     // write 3DExtrude shape
308                     SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_EXTRUDE, sal_True, sal_True);
309                 }
310                 break;
311             }
312             default:
313                 break;
314         }
315     }
316 }
317 
318 //////////////////////////////////////////////////////////////////////////////
319 
320 /** helper for chart that adds all attributes of a 3d scene element to the export */
321 void XMLShapeExport::export3DSceneAttributes( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet )
322 {
323     OUString aStr;
324     OUStringBuffer sStringBuffer;
325 
326     // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
327     uno::Any aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix")));
328     drawing::HomogenMatrix xHomMat;
329     aAny >>= xHomMat;
330     SdXMLImExTransform3D aTransform;
331     aTransform.AddHomogenMatrix(xHomMat);
332     if(aTransform.NeedsAction())
333         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
334 
335     // VRP, VPN, VUP
336     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DCameraGeometry")));
337     drawing::CameraGeometry aCamGeo;
338     aAny >>= aCamGeo;
339 
340     ::basegfx::B3DVector aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ);
341     if(aVRP != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
342     {
343         mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVRP);
344         aStr = sStringBuffer.makeStringAndClear();
345         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VRP, aStr);
346     }
347 
348     ::basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ);
349     if(aVPN != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
350     {
351         mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVPN);
352         aStr = sStringBuffer.makeStringAndClear();
353         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VPN, aStr);
354     }
355 
356     ::basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ);
357     if(aVUP != ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default
358     {
359         mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aVUP);
360         aStr = sStringBuffer.makeStringAndClear();
361         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_VUP, aStr);
362     }
363 
364     // projection "D3DScenePerspective" drawing::ProjectionMode
365     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DScenePerspective")));
366     drawing::ProjectionMode xPrjMode;
367     aAny >>= xPrjMode;
368     if(xPrjMode == drawing::ProjectionMode_PARALLEL)
369         aStr = GetXMLToken(XML_PARALLEL);
370     else
371         aStr = GetXMLToken(XML_PERSPECTIVE);
372     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_PROJECTION, aStr);
373 
374     // distance
375     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneDistance")));
376     sal_Int32 nDistance = 0;
377     aAny >>= nDistance;
378     mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nDistance);
379     aStr = sStringBuffer.makeStringAndClear();
380     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DISTANCE, aStr);
381 
382     // focalLength
383     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneFocalLength")));
384     sal_Int32 nFocalLength = 0;
385     aAny >>= nFocalLength;
386     mrExport.GetMM100UnitConverter().convertMeasure(sStringBuffer, nFocalLength);
387     aStr = sStringBuffer.makeStringAndClear();
388     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_FOCAL_LENGTH, aStr);
389 
390     // shadowSlant
391     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadowSlant")));
392     sal_Int16 nShadowSlant = 0;
393     aAny >>= nShadowSlant;
394     mrExport.GetMM100UnitConverter().convertNumber(sStringBuffer, (sal_Int32)nShadowSlant);
395     aStr = sStringBuffer.makeStringAndClear();
396     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADOW_SLANT, aStr);
397 
398     // shadeMode
399     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadeMode")));
400     drawing::ShadeMode xShadeMode;
401     if(aAny >>= xShadeMode)
402     {
403         if(xShadeMode == drawing::ShadeMode_FLAT)
404             aStr = GetXMLToken(XML_FLAT);
405         else if(xShadeMode == drawing::ShadeMode_PHONG)
406             aStr = GetXMLToken(XML_PHONG);
407         else if(xShadeMode == drawing::ShadeMode_SMOOTH)
408             aStr = GetXMLToken(XML_GOURAUD);
409         else
410             aStr = GetXMLToken(XML_DRAFT);
411     }
412     else
413     {
414         // ShadeMode enum not there, write default
415         aStr = GetXMLToken(XML_GOURAUD);
416     }
417     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADE_MODE, aStr);
418 
419     // ambientColor
420     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneAmbientColor")));
421     sal_Int32 aColTemp = 0;
422     Color aAmbientColor;
423     aAny >>= aColTemp; aAmbientColor.SetColor(aColTemp);
424     mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aAmbientColor);
425     aStr = sStringBuffer.makeStringAndClear();
426     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_AMBIENT_COLOR, aStr);
427 
428     // lightingMode
429     aAny = xPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneTwoSidedLighting")));
430     sal_Bool bTwoSidedLighting = false;
431     aAny >>= bTwoSidedLighting;
432     mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bTwoSidedLighting);
433     aStr = sStringBuffer.makeStringAndClear();
434     mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_LIGHTING_MODE, aStr);
435 }
436 
437 /** helper for chart that exports all lamps from the propertyset */
438 void XMLShapeExport::export3DLamps( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet )
439 {
440     // write lamps 1..8 as content
441     OUString aStr;
442     OUStringBuffer sStringBuffer;
443 
444     const OUString aColorPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor") );
445     const OUString aDirectionPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection") );
446     const OUString aLightOnPropName(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn") );
447 
448     OUString aPropName;
449     OUString aIndexStr;
450     sal_Int32 aColTemp = 0;
451     Color aLightColor;
452     ::basegfx::B3DVector aLightDirection;
453     drawing::Direction3D xLightDir;
454     sal_Bool bLightOnOff = false;
455     for(sal_Int32 nLamp = 1; nLamp <= 8; nLamp++)
456     {
457         aIndexStr = OUString::valueOf( nLamp );
458 
459         // lightcolor
460         aPropName = aColorPropName;
461         aPropName += aIndexStr;
462         xPropSet->getPropertyValue( aPropName ) >>= aColTemp;
463         aLightColor.SetColor(aColTemp);
464         mrExport.GetMM100UnitConverter().convertColor(sStringBuffer, aLightColor);
465         aStr = sStringBuffer.makeStringAndClear();
466         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIFFUSE_COLOR, aStr);
467 
468         // lightdirection
469         aPropName = aDirectionPropName;
470         aPropName += aIndexStr;
471         xPropSet->getPropertyValue(aPropName) >>= xLightDir;
472         aLightDirection = ::basegfx::B3DVector(xLightDir.DirectionX, xLightDir.DirectionY, xLightDir.DirectionZ);
473         mrExport.GetMM100UnitConverter().convertB3DVector(sStringBuffer, aLightDirection);
474         aStr = sStringBuffer.makeStringAndClear();
475         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_DIRECTION, aStr);
476 
477         // lighton
478         aPropName = aLightOnPropName;
479         aPropName += aIndexStr;
480         xPropSet->getPropertyValue(aPropName) >>= bLightOnOff;
481         mrExport.GetMM100UnitConverter().convertBool(sStringBuffer, bLightOnOff);
482         aStr = sStringBuffer.makeStringAndClear();
483         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_ENABLED, aStr);
484 
485         // specular
486         mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SPECULAR,
487             nLamp == 1 ? XML_TRUE : XML_FALSE);
488 
489         // write light entry
490         SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DR3D, XML_LIGHT, sal_True, sal_True);
491     }
492 }
493 
494 //////////////////////////////////////////////////////////////////////////////
495