LibreOffice Module xmloff (master)  1
ximp3dscene.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sax/tools/converter.hxx>
21 #include <rtl/math.hxx>
22 #include <sal/log.hxx>
23 
24 #include "ximp3dscene.hxx"
25 #include <xmloff/xmluconv.hxx>
26 #include <xexptran.hxx>
27 #include <xmloff/xmltoken.hxx>
28 #include <xmloff/xmlnmspe.hxx>
29 #include <com/sun/star/beans/XPropertySet.hpp>
30 #include <com/sun/star/drawing/Direction3D.hpp>
31 #include <com/sun/star/drawing/CameraGeometry.hpp>
32 #include "eventimp.hxx"
33 #include "descriptionimp.hxx"
34 
35 using namespace ::com::sun::star;
36 using namespace ::xmloff::token;
37 
38 // dr3d:3dlight context
39 
41  SvXMLImport& rImport,
42  sal_uInt16 nPrfx,
43  const OUString& rLName,
44  const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList)
45 : SvXMLImportContext( rImport, nPrfx, rLName),
46  maDiffuseColor(0x00000000),
47  maDirection(0.0, 0.0, 1.0),
48  mbEnabled(false),
49  mbSpecular(false)
50 {
51  // read attributes for the 3DScene
52  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
53  for(sal_Int16 i=0; i < nAttrCount; i++)
54  {
55  OUString sAttrName = xAttrList->getNameByIndex( i );
56  OUString aLocalName;
57  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
58  OUString sValue = xAttrList->getValueByIndex( i );
59  const SvXMLTokenMap& rAttrTokenMap = GetImport().GetShapeImport()->Get3DLightAttrTokenMap();
60 
61  switch(rAttrTokenMap.Get(nPrefix, aLocalName))
62  {
64  {
66  break;
67  }
69  {
72  if (!std::isnan(aVal.getX()) && !std::isnan(aVal.getY()) && !std::isnan(aVal.getZ()))
73  {
74  maDirection = aVal;
75  }
76  else
77  {
78  SAL_WARN("xmloff", "NaNs found in light direction: " << sValue);
79  }
80  break;
81  }
83  {
85  break;
86  }
88  {
90  break;
91  }
92  }
93  }
94 }
95 
97 {
98 }
99 
100 
102  SvXMLImport& rImport,
103  sal_uInt16 nPrfx,
104  const OUString& rLocalName,
105  const css::uno::Reference< css::xml::sax::XAttributeList>& xAttrList,
106  uno::Reference< drawing::XShapes > const & rShapes,
107  bool bTemporaryShapes)
108 : SdXMLShapeContext( rImport, nPrfx, rLocalName, xAttrList, rShapes, bTemporaryShapes ), SdXML3DSceneAttributesHelper( rImport )
109 {
110 }
111 
113 {
114 }
115 
116 void SdXML3DSceneShapeContext::StartElement(const uno::Reference< xml::sax::XAttributeList>& xAttrList)
117 {
118  // create new 3DScene shape and add it to rShapes, use it
119  // as base for the new 3DScene import
120  AddShape( "com.sun.star.drawing.Shape3DSceneObject" );
121  if( mxShape.is() )
122  {
123  SetStyle();
124 
125  mxChildren.set( mxShape, uno::UNO_QUERY );
126  if( mxChildren.is() )
127  GetImport().GetShapeImport()->pushGroupForPostProcessing( mxChildren );
128 
129  SetLayer();
130 
131  // set pos, size, shear and rotate
133  }
134 
135  // read attributes for the 3DScene
136  sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
137  for(sal_Int16 i=0; i < nAttrCount; i++)
138  {
139  OUString sAttrName = xAttrList->getNameByIndex( i );
140  OUString aLocalName;
141  sal_uInt16 nPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sAttrName, &aLocalName );
142  OUString sValue = xAttrList->getValueByIndex( i );
143  processSceneAttribute( nPrefix, aLocalName, sValue );
144  }
145 
146  // #91047# call parent function is missing here, added it
147  if(mxShape.is())
148  {
149  // call parent
151  }
152 }
153 
155 {
156  if(mxShape.is())
157  {
158  uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
159  if(xPropSet.is())
160  {
161  setSceneAttributes( xPropSet );
162  }
163 
164  if( mxChildren.is() )
165  GetImport().GetShapeImport()->popGroupAndPostProcess();
166 
167  // call parent
169  }
170 }
171 
173  const OUString& rLocalName,
174  const uno::Reference< xml::sax::XAttributeList>& xAttrList )
175 {
176  SvXMLImportContextRef xContext;
177 
178  // #i68101#
179  if( nPrefix == XML_NAMESPACE_SVG &&
180  (IsXMLToken( rLocalName, XML_TITLE ) || IsXMLToken( rLocalName, XML_DESC ) ) )
181  {
182  xContext = new SdXMLDescriptionContext( GetImport(), nPrefix, rLocalName, xAttrList, mxShape );
183  }
184  else if( nPrefix == XML_NAMESPACE_OFFICE && IsXMLToken( rLocalName, XML_EVENT_LISTENERS ) )
185  {
186  xContext = new SdXMLEventsContext( GetImport(), nPrefix, rLocalName, xAttrList, mxShape );
187  }
188  // look for local light context first
189  else if(nPrefix == XML_NAMESPACE_DR3D && IsXMLToken( rLocalName, XML_LIGHT ) )
190  {
191  // dr3d:light inside dr3d:scene context
192  xContext = create3DLightContext( nPrefix, rLocalName, xAttrList );
193  }
194 
195  // call GroupChildContext function at common ShapeImport
196  if (!xContext)
197  {
198  xContext = GetImport().GetShapeImport()->Create3DSceneChildContext(
199  GetImport(), nPrefix, rLocalName, xAttrList, mxChildren);
200  }
201 
202  return xContext;
203 }
204 
206 : mrImport( rImporter ),
207  mbSetTransform( false ),
208  mxPrjMode(drawing::ProjectionMode_PERSPECTIVE),
209  mnDistance(1000),
210  mnFocalLength(1000),
211  mnShadowSlant(0),
212  mxShadeMode(drawing::ShadeMode_SMOOTH),
213  maAmbientColor(0x00666666),
214  mbLightingMode(false),
215  maVRP(0.0, 0.0, 1.0),
216  maVPN(0.0, 0.0, 1.0),
217  maVUP(0.0, 1.0, 0.0),
218  mbVRPUsed(false),
219  mbVPNUsed(false),
220  mbVUPUsed(false)
221 {
222 }
223 
225 SvXMLImportContext * SdXML3DSceneAttributesHelper::create3DLightContext( sal_uInt16 nPrfx, const OUString& rLName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttrList)
226 {
227  const rtl::Reference<SdXML3DLightContext> xContext{new SdXML3DLightContext(mrImport, nPrfx, rLName, xAttrList)};
228 
229  // remember SdXML3DLightContext for later evaluation
230  maList.push_back(xContext);
231 
232  return xContext.get();
233 }
234 
236 void SdXML3DSceneAttributesHelper::processSceneAttribute( sal_uInt16 nPrefix, const OUString& rLocalName, const OUString& rValue )
237 {
238  if( XML_NAMESPACE_DR3D == nPrefix )
239  {
240  if( IsXMLToken( rLocalName, XML_TRANSFORM ) )
241  {
243  if(aTransform.NeedsAction())
244  mbSetTransform = aTransform.GetFullHomogenTransform(mxHomMat);
245  return;
246  }
247  else if( IsXMLToken( rLocalName, XML_VRP ) )
248  {
249  ::basegfx::B3DVector aNewVec;
250  SvXMLUnitConverter::convertB3DVector(aNewVec, rValue);
251 
252  if(aNewVec != maVRP)
253  {
254  maVRP = aNewVec;
255  mbVRPUsed = true;
256  }
257  return;
258  }
259  else if( IsXMLToken( rLocalName, XML_VPN ) )
260  {
261  ::basegfx::B3DVector aNewVec;
262  SvXMLUnitConverter::convertB3DVector(aNewVec, rValue);
263 
264  if(aNewVec != maVPN)
265  {
266  maVPN = aNewVec;
267  mbVPNUsed = true;
268  }
269  return;
270  }
271  else if( IsXMLToken( rLocalName, XML_VUP ) )
272  {
273  ::basegfx::B3DVector aNewVec;
274  SvXMLUnitConverter::convertB3DVector(aNewVec, rValue);
275 
276  if(aNewVec != maVUP)
277  {
278  maVUP = aNewVec;
279  mbVUPUsed = true;
280  }
281  return;
282  }
283  else if( IsXMLToken( rLocalName, XML_PROJECTION ) )
284  {
285  if( IsXMLToken( rValue, XML_PARALLEL ) )
286  mxPrjMode = drawing::ProjectionMode_PARALLEL;
287  else
288  mxPrjMode = drawing::ProjectionMode_PERSPECTIVE;
289  return;
290  }
291  else if( IsXMLToken( rLocalName, XML_DISTANCE ) )
292  {
294  rValue);
295  return;
296  }
297  else if( IsXMLToken( rLocalName, XML_FOCAL_LENGTH ) )
298  {
300  rValue);
301  return;
302  }
303  else if( IsXMLToken( rLocalName, XML_SHADOW_SLANT ) )
304  {
306  return;
307  }
308  else if( IsXMLToken( rLocalName, XML_SHADE_MODE ) )
309  {
310  if( IsXMLToken( rValue, XML_FLAT ) )
311  mxShadeMode = drawing::ShadeMode_FLAT;
312  else if( IsXMLToken( rValue, XML_PHONG ) )
313  mxShadeMode = drawing::ShadeMode_PHONG;
314  else if( IsXMLToken( rValue, XML_GOURAUD ) )
315  mxShadeMode = drawing::ShadeMode_SMOOTH;
316  else
317  mxShadeMode = drawing::ShadeMode_DRAFT;
318  return;
319  }
320  else if( IsXMLToken( rLocalName, XML_AMBIENT_COLOR ) )
321  {
323  return;
324  }
325  else if( IsXMLToken( rLocalName, XML_LIGHTING_MODE ) )
326  {
328  return;
329  }
330  }
331 }
332 
334 void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
335 {
336  uno::Any aAny;
337 
338  // world transformation
339  if(mbSetTransform)
340  {
341  xPropSet->setPropertyValue("D3DTransformMatrix", uno::Any(mxHomMat));
342  }
343 
344  // distance
345  xPropSet->setPropertyValue("D3DSceneDistance", uno::Any(mnDistance));
346  // focalLength
347  xPropSet->setPropertyValue("D3DSceneFocalLength", uno::Any(mnFocalLength));
348  // shadowSlant
349  xPropSet->setPropertyValue("D3DSceneShadowSlant", uno::Any(static_cast<sal_Int16>(mnShadowSlant)));
350  // shadeMode
351  xPropSet->setPropertyValue("D3DSceneShadeMode", uno::Any(mxShadeMode));
352  // ambientColor
353  xPropSet->setPropertyValue("D3DSceneAmbientColor", uno::Any(maAmbientColor));
354  // lightingMode
355  xPropSet->setPropertyValue("D3DSceneTwoSidedLighting", uno::Any(mbLightingMode));
356 
357  if( !maList.empty() )
358  {
359  uno::Any aAny2;
360  uno::Any aAny3;
361 
362  // set lights
363  for( size_t a = 0; a < maList.size(); a++)
364  {
365  SdXML3DLightContext* pCtx = maList[ a ].get();
366 
367  // set anys
368  aAny <<= pCtx->GetDiffuseColor();
369  drawing::Direction3D aLightDir;
370  aLightDir.DirectionX = pCtx->GetDirection().getX();
371  aLightDir.DirectionY = pCtx->GetDirection().getY();
372  aLightDir.DirectionZ = pCtx->GetDirection().getZ();
373  aAny2 <<= aLightDir;
374  aAny3 <<= pCtx->GetEnabled();
375 
376  switch(a)
377  {
378  case 0:
379  {
380  xPropSet->setPropertyValue("D3DSceneLightColor1", aAny);
381  xPropSet->setPropertyValue("D3DSceneLightDirection1", aAny2);
382  xPropSet->setPropertyValue("D3DSceneLightOn1", aAny3);
383  break;
384  }
385  case 1:
386  {
387  xPropSet->setPropertyValue("D3DSceneLightColor2", aAny);
388  xPropSet->setPropertyValue("D3DSceneLightDirection2", aAny2);
389  xPropSet->setPropertyValue("D3DSceneLightOn2", aAny3);
390  break;
391  }
392  case 2:
393  {
394  xPropSet->setPropertyValue("D3DSceneLightColor3", aAny);
395  xPropSet->setPropertyValue("D3DSceneLightDirection3", aAny2);
396  xPropSet->setPropertyValue("D3DSceneLightOn3", aAny3);
397  break;
398  }
399  case 3:
400  {
401  xPropSet->setPropertyValue("D3DSceneLightColor4", aAny);
402  xPropSet->setPropertyValue("D3DSceneLightDirection4", aAny2);
403  xPropSet->setPropertyValue("D3DSceneLightOn4", aAny3);
404  break;
405  }
406  case 4:
407  {
408  xPropSet->setPropertyValue("D3DSceneLightColor5", aAny);
409  xPropSet->setPropertyValue("D3DSceneLightDirection5", aAny2);
410  xPropSet->setPropertyValue("D3DSceneLightOn5", aAny3);
411  break;
412  }
413  case 5:
414  {
415  xPropSet->setPropertyValue("D3DSceneLightColor6", aAny);
416  xPropSet->setPropertyValue("D3DSceneLightDirection6", aAny2);
417  xPropSet->setPropertyValue("D3DSceneLightOn6", aAny3);
418  break;
419  }
420  case 6:
421  {
422  xPropSet->setPropertyValue("D3DSceneLightColor7", aAny);
423  xPropSet->setPropertyValue("D3DSceneLightDirection7", aAny2);
424  xPropSet->setPropertyValue("D3DSceneLightOn7", aAny3);
425  break;
426  }
427  case 7:
428  {
429  xPropSet->setPropertyValue("D3DSceneLightColor8", aAny);
430  xPropSet->setPropertyValue("D3DSceneLightDirection8", aAny2);
431  xPropSet->setPropertyValue("D3DSceneLightOn8", aAny3);
432  break;
433  }
434  }
435  }
436  }
437 
438  // CameraGeometry and camera settings
439  drawing::CameraGeometry aCamGeo;
440  aCamGeo.vrp.PositionX = maVRP.getX();
441  aCamGeo.vrp.PositionY = maVRP.getY();
442  aCamGeo.vrp.PositionZ = maVRP.getZ();
443  aCamGeo.vpn.DirectionX = maVPN.getX();
444  aCamGeo.vpn.DirectionY = maVPN.getY();
445  aCamGeo.vpn.DirectionZ = maVPN.getZ();
446  aCamGeo.vup.DirectionX = maVUP.getX();
447  aCamGeo.vup.DirectionY = maVUP.getY();
448  aCamGeo.vup.DirectionZ = maVUP.getZ();
449  xPropSet->setPropertyValue("D3DCameraGeometry", uno::Any(aCamGeo));
450 
451  // #91047# set drawing::ProjectionMode AFTER camera geometry is set
452  // projection "D3DScenePerspective" drawing::ProjectionMode
453  xPropSet->setPropertyValue("D3DScenePerspective", uno::Any(mxPrjMode));
454 }
455 
456 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetTransformation()
Definition: ximpshap.cxx:533
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3422
static bool convertBool(bool &rBool, const OUString &rString)
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
Definition: ximpshap.cxx:346
sal_Int32 GetDiffuseColor() const
void setSceneAttributes(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
this sets the scene attributes at this propertyset
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:62
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:397
sal_uInt16 GetKeyByAttrName(const OUString &rAttrName, OUString *pPrefix, OUString *pLocalName, OUString *pNamespace) const
Definition: nmspmap.cxx:437
sal_Int32 maDiffuseColor
void AddShape(css::uno::Reference< css::drawing::XShape > &xShape)
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
bool convertMeasureToCore(sal_Int32 &rValue, const OUString &rString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32) const
convert string to measure with meCoreMeasureUnit, using optional min and max values ...
Definition: xmluconv.cxx:171
css::uno::Reference< css::drawing::XShapes > mxChildren
Definition: ximp3dscene.hxx:33
virtual void EndElement() override
EndElement is called before a context will be destructed, but after an elements context has been pars...
SdXML3DSceneShapeContext(SvXMLImport &rImport, sal_uInt16 nPrfx, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > const &rShapes, bool bTemporaryShape)
virtual SvXMLImportContextRef CreateChildContext(sal_uInt16 nPrefix, const OUString &rLocalName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
Create a children element context.
bool GetEnabled() const
::basegfx::B3DVector maVUP
int i
virtual ~SdXML3DLightContext() override
Definition: ximp3dscene.cxx:96
uno_Any a
css::drawing::ShadeMode mxShadeMode
::basegfx::B3DVector maVPN
SdXML3DSceneAttributesHelper(SvXMLImport &rImporter)
css::uno::Reference< css::drawing::XShape > mxShape
sal_uInt16 Get(sal_uInt16 nPrefix, const OUString &rLName) const
Definition: xmltkmap.cxx:93
SvXMLImportContext * create3DLightContext(sal_uInt16 nPrfx, const OUString &rLName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
creates a 3d light context and adds it to the internal list for later processing
const ::basegfx::B3DVector & GetDirection() const
void processSceneAttribute(sal_uInt16 nPrefix, const OUString &rLocalName, const OUString &rValue)
this should be called for each scene attribute
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:44
static bool convertB3DVector(::basegfx::B3DVector &rVector, const OUString &rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:507
SdXML3DLightContext(SvXMLImport &rImport, sal_uInt16 nPrfx, const OUString &rLName, const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList)
Definition: ximp3dscene.cxx:40
constexpr sal_uInt16 XML_NAMESPACE_DR3D
Definition: xmlnmspe.hxx:42
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
Definition: ximpshap.cxx:341
static bool convertColor(sal_Int32 &rColor, const OUString &rValue)
Handling of tokens in XML:
void SetStyle(bool bSupportsStyle=true)
if bSupportsStyle is false, auto styles will be set but not a style
Definition: ximpshap.cxx:611
::basegfx::B3DVector maDirection
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:399
virtual ~SdXML3DSceneShapeContext() override
#define SAL_WARN(area, stream)
css::drawing::ProjectionMode mxPrjMode
::basegfx::B3DVector maVRP
constexpr sal_uInt16 XML_NAMESPACE_SVG
Definition: xmlnmspe.hxx:40
virtual void StartElement(const css::uno::Reference< css::xml::sax::XAttributeList > &xAttrList) override
StartElement is called after a context has been constructed and before an elements context is parsed...
::std::vector< rtl::Reference< SdXML3DLightContext > > maList
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:602
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
Definition: xmlnmspe.hxx:29
static bool convertNumber(sal_Int32 &rValue, std::u16string_view aString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
css::drawing::HomogenMatrix mxHomMat
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo