xref: /trunk/main/xmloff/source/draw/ximp3dscene.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 "ximp3dscene.hxx"
31 #include <xmloff/xmluconv.hxx>
32 #include "xexptran.hxx"
33 #include <xmloff/xmltoken.hxx>
34 #include "xmloff/xmlnmspe.hxx"
35 #include <com/sun/star/drawing/Direction3D.hpp>
36 #include <com/sun/star/drawing/CameraGeometry.hpp>
37 #include "eventimp.hxx"
38 #include "descriptionimp.hxx"
39 
40 using ::rtl::OUString;
41 using ::rtl::OUStringBuffer;
42 
43 using namespace ::com::sun::star;
44 using namespace ::xmloff::token;
45 
46 //////////////////////////////////////////////////////////////////////////////
47 // dr3d:3dlight context
48 
49 SdXML3DLightContext::SdXML3DLightContext(
50     SvXMLImport& rImport,
51     sal_uInt16 nPrfx,
52     const rtl::OUString& rLName,
53     const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList)
54 :   SvXMLImportContext( rImport, nPrfx, rLName),
55     maDiffuseColor(0x00000000),
56     maDirection(0.0, 0.0, 1.0),
57     mbEnabled(sal_False),
58     mbSpecular(sal_False)
59 {
60     // read attributes for the 3DScene
61     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
62     for(sal_Int16 i=0; i < nAttrCount; i++)
63     {
64         OUString sAttrName = xAttrList->getNameByIndex( i );
65         OUString aLocalName;
66         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
67         OUString sValue = xAttrList->getValueByIndex( i );
68         const SvXMLTokenMap& rAttrTokenMap = GetImport().GetShapeImport()->Get3DLightAttrTokenMap();
69 
70         switch(rAttrTokenMap.Get(nPrefix, aLocalName))
71         {
72             case XML_TOK_3DLIGHT_DIFFUSE_COLOR:
73             {
74                 GetImport().GetMM100UnitConverter().convertColor(maDiffuseColor, sValue);
75                 break;
76             }
77             case XML_TOK_3DLIGHT_DIRECTION:
78             {
79                 GetImport().GetMM100UnitConverter().convertB3DVector(maDirection, sValue);
80                 break;
81             }
82             case XML_TOK_3DLIGHT_ENABLED:
83             {
84                 GetImport().GetMM100UnitConverter().convertBool(mbEnabled, sValue);
85                 break;
86             }
87             case XML_TOK_3DLIGHT_SPECULAR:
88             {
89                 GetImport().GetMM100UnitConverter().convertBool(mbSpecular, sValue);
90                 break;
91             }
92         }
93     }
94 }
95 
96 SdXML3DLightContext::~SdXML3DLightContext()
97 {
98 }
99 
100 //////////////////////////////////////////////////////////////////////////////
101 
102 TYPEINIT1( SdXML3DSceneShapeContext, SdXMLShapeContext );
103 
104 SdXML3DSceneShapeContext::SdXML3DSceneShapeContext(
105     SvXMLImport& rImport,
106     sal_uInt16 nPrfx,
107     const OUString& rLocalName,
108     const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList>& xAttrList,
109     uno::Reference< drawing::XShapes >& rShapes,
110     sal_Bool bTemporaryShapes)
111 :   SdXMLShapeContext( rImport, nPrfx, rLocalName, xAttrList, rShapes, bTemporaryShapes ), SdXML3DSceneAttributesHelper( rImport )
112 {
113 }
114 
115 //////////////////////////////////////////////////////////////////////////////
116 
117 SdXML3DSceneShapeContext::~SdXML3DSceneShapeContext()
118 {
119 }
120 
121 //////////////////////////////////////////////////////////////////////////////
122 
123 void SdXML3DSceneShapeContext::StartElement(const uno::Reference< xml::sax::XAttributeList>& xAttrList)
124 {
125     // create new 3DScene shape and add it to rShapes, use it
126     // as base for the new 3DScene import
127     AddShape( "com.sun.star.drawing.Shape3DSceneObject" );
128     if( mxShape.is() )
129     {
130         SetStyle();
131 
132         mxChilds = uno::Reference< drawing::XShapes >::query( mxShape );
133         if( mxChilds.is() )
134             GetImport().GetShapeImport()->pushGroupForSorting( mxChilds );
135 
136         SetLayer();
137 
138         // set pos, size, shear and rotate
139         SetTransformation();
140     }
141 
142     // read attributes for the 3DScene
143     sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
144     for(sal_Int16 i=0; i < nAttrCount; i++)
145     {
146         OUString sAttrName = xAttrList->getNameByIndex( i );
147         OUString aLocalName;
148         sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
149         OUString sValue = xAttrList->getValueByIndex( i );
150         processSceneAttribute( nPrefix, aLocalName, sValue );
151     }
152 
153     // #91047# call parent function is missing here, added it
154     if(mxShape.is())
155     {
156         // call parent
157         SdXMLShapeContext::StartElement(xAttrList);
158     }
159 }
160 
161 //////////////////////////////////////////////////////////////////////////////
162 
163 void SdXML3DSceneShapeContext::EndElement()
164 {
165     if(mxShape.is())
166     {
167         uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
168         if(xPropSet.is())
169         {
170             setSceneAttributes( xPropSet );
171         }
172 
173         if( mxChilds.is() )
174             GetImport().GetShapeImport()->popGroupAndSort();
175 
176         // call parent
177         SdXMLShapeContext::EndElement();
178     }
179 }
180 
181 //////////////////////////////////////////////////////////////////////////////
182 
183 SvXMLImportContext* SdXML3DSceneShapeContext::CreateChildContext( sal_uInt16 nPrefix,
184     const OUString& rLocalName,
185     const uno::Reference< xml::sax::XAttributeList>& xAttrList )
186 {
187     SvXMLImportContext* pContext = 0L;
188 
189     // #i68101#
190     if( nPrefix == XML_NAMESPACE_SVG &&
191         (IsXMLToken( rLocalName, XML_TITLE ) || IsXMLToken( rLocalName, XML_DESC ) ) )
192     {
193         pContext = new SdXMLDescriptionContext( GetImport(), nPrefix, rLocalName, xAttrList, mxShape );
194     }
195     else if( nPrefix == XML_NAMESPACE_OFFICE && IsXMLToken( rLocalName, XML_EVENT_LISTENERS ) )
196     {
197         pContext = new SdXMLEventsContext( GetImport(), nPrefix, rLocalName, xAttrList, mxShape );
198     }
199     // look for local light context first
200     else if(nPrefix == XML_NAMESPACE_DR3D && IsXMLToken( rLocalName, XML_LIGHT ) )
201     {
202         // dr3d:light inside dr3d:scene context
203         pContext = create3DLightContext( nPrefix, rLocalName, xAttrList );
204     }
205 
206     // call GroupChildContext function at common ShapeImport
207     if(!pContext)
208     {
209         pContext = GetImport().GetShapeImport()->Create3DSceneChildContext(
210             GetImport(), nPrefix, rLocalName, xAttrList, mxChilds);
211         }
212 
213     // call parent when no own context was created
214     if(!pContext)
215     {
216         pContext = SvXMLImportContext::CreateChildContext(
217         nPrefix, rLocalName, xAttrList);
218     }
219 
220     return pContext;
221 }
222 
223 //////////////////////////////////////////////////////////////////////////////
224 
225 SdXML3DSceneAttributesHelper::SdXML3DSceneAttributesHelper( SvXMLImport& rImporter )
226 :   mrImport( rImporter ),
227     mbSetTransform( sal_False ),
228     mxPrjMode(drawing::ProjectionMode_PERSPECTIVE),
229     mnDistance(1000),
230     mnFocalLength(1000),
231     mnShadowSlant(0),
232     mxShadeMode(drawing::ShadeMode_SMOOTH),
233     maAmbientColor(0x00666666),
234     mbLightingMode(sal_False),
235     maVRP(0.0, 0.0, 1.0),
236     maVPN(0.0, 0.0, 1.0),
237     maVUP(0.0, 1.0, 0.0),
238     mbVRPUsed(sal_False),
239     mbVPNUsed(sal_False),
240     mbVUPUsed(sal_False)
241 {
242 }
243 
244 SdXML3DSceneAttributesHelper::~SdXML3DSceneAttributesHelper()
245 {
246     // release remembered light contexts, they are no longer needed
247     while(maList.Count())
248         maList.Remove(maList.Count() - 1)->ReleaseRef();
249 }
250 
251 /** creates a 3d ligth context and adds it to the internal list for later processing */
252 SvXMLImportContext * SdXML3DSceneAttributesHelper::create3DLightContext( sal_uInt16 nPrfx, const rtl::OUString& rLName, const com::sun::star::uno::Reference< com::sun::star::xml::sax::XAttributeList >& xAttrList)
253 {
254     SvXMLImportContext* pContext = new SdXML3DLightContext(mrImport, nPrfx, rLName, xAttrList);
255 
256     // remember SdXML3DLightContext for later evaluation
257     if(pContext)
258     {
259         pContext->AddRef();
260         maList.Insert((SdXML3DLightContext*)pContext, LIST_APPEND);
261     }
262 
263     return pContext;
264 }
265 
266 /** this should be called for each scene attribute */
267 void SdXML3DSceneAttributesHelper::processSceneAttribute( sal_uInt16 nPrefix, const ::rtl::OUString& rLocalName, const ::rtl::OUString& rValue )
268 {
269     if( XML_NAMESPACE_DR3D == nPrefix )
270     {
271         if( IsXMLToken( rLocalName, XML_TRANSFORM ) )
272         {
273             SdXMLImExTransform3D aTransform(rValue, mrImport.GetMM100UnitConverter());
274             if(aTransform.NeedsAction())
275                 mbSetTransform = aTransform.GetFullHomogenTransform(mxHomMat);
276             return;
277         }
278         else if( IsXMLToken( rLocalName, XML_VRP ) )
279         {
280             ::basegfx::B3DVector aNewVec;
281             mrImport.GetMM100UnitConverter().convertB3DVector(aNewVec, rValue);
282 
283             if(aNewVec != maVRP)
284             {
285                 maVRP = aNewVec;
286                 mbVRPUsed = sal_True;
287             }
288             return;
289         }
290         else if( IsXMLToken( rLocalName, XML_VPN ) )
291         {
292             ::basegfx::B3DVector aNewVec;
293             mrImport.GetMM100UnitConverter().convertB3DVector(aNewVec, rValue);
294 
295             if(aNewVec != maVPN)
296             {
297                 maVPN = aNewVec;
298                 mbVPNUsed = sal_True;
299             }
300             return;
301         }
302         else if( IsXMLToken( rLocalName, XML_VUP ) )
303         {
304             ::basegfx::B3DVector aNewVec;
305             mrImport.GetMM100UnitConverter().convertB3DVector(aNewVec, rValue);
306 
307             if(aNewVec != maVUP)
308             {
309                 maVUP = aNewVec;
310                 mbVUPUsed = sal_True;
311             }
312             return;
313         }
314         else if( IsXMLToken( rLocalName, XML_PROJECTION ) )
315         {
316             if( IsXMLToken( rValue, XML_PARALLEL ) )
317                 mxPrjMode = drawing::ProjectionMode_PARALLEL;
318             else
319                 mxPrjMode = drawing::ProjectionMode_PERSPECTIVE;
320             return;
321         }
322         else if( IsXMLToken( rLocalName, XML_DISTANCE ) )
323         {
324             mrImport.GetMM100UnitConverter().convertMeasure(mnDistance, rValue);
325             return;
326         }
327         else if( IsXMLToken( rLocalName, XML_FOCAL_LENGTH ) )
328         {
329             mrImport.GetMM100UnitConverter().convertMeasure(mnFocalLength, rValue);
330             return;
331         }
332         else if( IsXMLToken( rLocalName, XML_SHADOW_SLANT ) )
333         {
334             mrImport.GetMM100UnitConverter().convertNumber(mnShadowSlant, rValue);
335             return;
336         }
337         else if( IsXMLToken( rLocalName, XML_SHADE_MODE ) )
338         {
339             if( IsXMLToken( rValue, XML_FLAT ) )
340                 mxShadeMode = drawing::ShadeMode_FLAT;
341             else if( IsXMLToken( rValue, XML_PHONG ) )
342                 mxShadeMode = drawing::ShadeMode_PHONG;
343             else if( IsXMLToken( rValue, XML_GOURAUD ) )
344                 mxShadeMode = drawing::ShadeMode_SMOOTH;
345             else
346                 mxShadeMode = drawing::ShadeMode_DRAFT;
347             return;
348         }
349         else if( IsXMLToken( rLocalName, XML_AMBIENT_COLOR ) )
350         {
351             mrImport.GetMM100UnitConverter().convertColor(maAmbientColor, rValue);
352             return;
353         }
354         else if( IsXMLToken( rLocalName, XML_LIGHTING_MODE ) )
355         {
356             mrImport.GetMM100UnitConverter().convertBool(mbLightingMode, rValue);
357             return;
358         }
359     }
360 }
361 
362 /** this sets the scene attributes at this propertyset */
363 void SdXML3DSceneAttributesHelper::setSceneAttributes( const com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet >& xPropSet )
364 {
365     uno::Any aAny;
366 
367     // world transformation
368     if(mbSetTransform)
369     {
370         aAny <<= mxHomMat;
371         xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DTransformMatrix")), aAny);
372     }
373 
374     // distance
375     aAny <<= mnDistance;
376     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneDistance")), aAny);
377 
378     // focalLength
379     aAny <<= mnFocalLength;
380     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneFocalLength")), aAny);
381 
382     // shadowSlant
383     aAny <<= (sal_Int16)mnShadowSlant;
384     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadowSlant")), aAny);
385 
386     // shadeMode
387     aAny <<= mxShadeMode;
388     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneShadeMode")), aAny);
389 
390     // ambientColor
391     aAny <<= maAmbientColor.GetColor();
392     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneAmbientColor")), aAny);
393 
394     // lightingMode
395     aAny <<= mbLightingMode;
396     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneTwoSidedLighting")), aAny);
397 
398     if(maList.Count())
399     {
400         uno::Any aAny2;
401         uno::Any aAny3;
402 
403         // set lights
404         for(sal_uInt32 a(0L); a < maList.Count(); a++)
405         {
406             SdXML3DLightContext* pCtx = (SdXML3DLightContext*)maList.GetObject(a);
407 
408             // set anys
409             aAny <<= pCtx->GetDiffuseColor().GetColor();
410             drawing::Direction3D xLightDir;
411             xLightDir.DirectionX = pCtx->GetDirection().getX();
412             xLightDir.DirectionY = pCtx->GetDirection().getY();
413             xLightDir.DirectionZ = pCtx->GetDirection().getZ();
414             aAny2 <<= xLightDir;
415             aAny3 <<= pCtx->GetEnabled();
416 
417             switch(a)
418             {
419                 case 0:
420                 {
421                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor1")), aAny);
422                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection1")), aAny2);
423                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn1")), aAny3);
424                     break;
425                 }
426                 case 1:
427                 {
428                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor2")), aAny);
429                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection2")), aAny2);
430                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn2")), aAny3);
431                     break;
432                 }
433                 case 2:
434                 {
435                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor3")), aAny);
436                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection3")), aAny2);
437                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn3")), aAny3);
438                     break;
439                 }
440                 case 3:
441                 {
442                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor4")), aAny);
443                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection4")), aAny2);
444                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn4")), aAny3);
445                     break;
446                 }
447                 case 4:
448                 {
449                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor5")), aAny);
450                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection5")), aAny2);
451                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn5")), aAny3);
452                     break;
453                 }
454                 case 5:
455                 {
456                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor6")), aAny);
457                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection6")), aAny2);
458                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn6")), aAny3);
459                     break;
460                 }
461                 case 6:
462                 {
463                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor7")), aAny);
464                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection7")), aAny2);
465                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn7")), aAny3);
466                     break;
467                 }
468                 case 7:
469                 {
470                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightColor8")), aAny);
471                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightDirection8")), aAny2);
472                     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DSceneLightOn8")), aAny3);
473                     break;
474                 }
475             }
476         }
477     }
478 
479     // CameraGeometry and camera settings
480     drawing::CameraGeometry aCamGeo;
481     aCamGeo.vrp.PositionX = maVRP.getX();
482     aCamGeo.vrp.PositionY = maVRP.getY();
483     aCamGeo.vrp.PositionZ = maVRP.getZ();
484     aCamGeo.vpn.DirectionX = maVPN.getX();
485     aCamGeo.vpn.DirectionY = maVPN.getY();
486     aCamGeo.vpn.DirectionZ = maVPN.getZ();
487     aCamGeo.vup.DirectionX = maVUP.getX();
488     aCamGeo.vup.DirectionY = maVUP.getY();
489     aCamGeo.vup.DirectionZ = maVUP.getZ();
490     aAny <<= aCamGeo;
491     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DCameraGeometry")), aAny);
492 
493     // #91047# set drawing::ProjectionMode AFTER camera geometry is set
494     // projection "D3DScenePerspective" drawing::ProjectionMode
495     aAny <<= mxPrjMode;
496     xPropSet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("D3DScenePerspective")), aAny);
497 }
498