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/xmlnamespace.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  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
43 : SvXMLImportContext( rImport ),
44  maDiffuseColor(0x00000000),
45  maDirection(0.0, 0.0, 1.0),
46  mbEnabled(false),
47  mbSpecular(false)
48 {
49  // read attributes for the 3DScene
50  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
51  {
52  switch(aIter.getToken())
53  {
54  case XML_ELEMENT(DR3D, XML_DIFFUSE_COLOR):
55  {
57  break;
58  }
59  case XML_ELEMENT(DR3D, XML_DIRECTION):
60  {
62  SvXMLUnitConverter::convertB3DVector(aVal, aIter.toString());
63  if (!std::isnan(aVal.getX()) && !std::isnan(aVal.getY()) && !std::isnan(aVal.getZ()))
64  {
65  maDirection = aVal;
66  }
67  else
68  {
69  SAL_WARN("xmloff", "NaNs found in light direction: " << aIter.toString());
70  }
71  break;
72  }
73  case XML_ELEMENT(DR3D, XML_ENABLED):
74  {
75  (void)::sax::Converter::convertBool(mbEnabled, aIter.toView());
76  break;
77  }
78  case XML_ELEMENT(DR3D, XML_SPECULAR):
79  {
80  (void)::sax::Converter::convertBool(mbSpecular, aIter.toView());
81  break;
82  }
83  default:
84  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
85  }
86  }
87 }
88 
90 {
91 }
92 
93 
95  SvXMLImport& rImport,
96  const css::uno::Reference< css::xml::sax::XFastAttributeList>& xAttrList,
97  uno::Reference< drawing::XShapes > const & rShapes,
98  bool bTemporaryShapes)
99 : SdXMLShapeContext( rImport, xAttrList, rShapes, bTemporaryShapes ), SdXML3DSceneAttributesHelper( rImport )
100 {
101 }
102 
104 {
105 }
106 
108  sal_Int32 nElement,
109  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
110 {
111  // create new 3DScene shape and add it to rShapes, use it
112  // as base for the new 3DScene import
113  AddShape( "com.sun.star.drawing.Shape3DSceneObject" );
114  if( mxShape.is() )
115  {
116  SetStyle();
117 
118  mxChildren.set( mxShape, uno::UNO_QUERY );
119  if( mxChildren.is() )
120  GetImport().GetShapeImport()->pushGroupForPostProcessing( mxChildren );
121 
122  SetLayer();
123 
124  // set pos, size, shear and rotate
126  }
127 
128  // read attributes for the 3DScene
129  for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
130  processSceneAttribute( aIter );
131 
132  // #91047# call parent function is missing here, added it
133  if(mxShape.is())
134  {
135  // call parent
136  SdXMLShapeContext::startFastElement(nElement, xAttrList);
137  }
138 }
139 
141 {
142  if(!mxShape.is())
143  return;
144 
145  uno::Reference< beans::XPropertySet > xPropSet(mxShape, uno::UNO_QUERY);
146  if(xPropSet.is())
147  {
148  setSceneAttributes( xPropSet );
149  }
150 
151  if( mxChildren.is() )
152  GetImport().GetShapeImport()->popGroupAndPostProcess();
153 
154  // call parent
156 }
157 
158 css::uno::Reference< css::xml::sax::XFastContextHandler > SdXML3DSceneShapeContext::createFastChildContext(
159  sal_Int32 nElement,
160  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
161 {
162  SvXMLImportContextRef xContext;
163  switch (nElement)
164  {
165  // #i68101#
166  case XML_ELEMENT(SVG, XML_TITLE):
167  case XML_ELEMENT(SVG_COMPAT, XML_TITLE):
168  case XML_ELEMENT(SVG, XML_DESC):
169  case XML_ELEMENT(SVG_COMPAT, XML_DESC):
170  xContext = new SdXMLDescriptionContext( GetImport(), nElement, mxShape );
171  break;
173  xContext = new SdXMLEventsContext( GetImport(), mxShape );
174  break;
175  // look for local light context first
176  case XML_ELEMENT(DR3D, XML_LIGHT):
177  // dr3d:light inside dr3d:scene context
178  xContext = create3DLightContext( xAttrList );
179  break;
180  default:
181  // call GroupChildContext function at common ShapeImport
183  GetImport(), nElement, xAttrList, mxChildren);
184  }
185  return xContext.get();
186 }
187 
189 : mrImport( rImporter ),
190  mbSetTransform( false ),
191  mxPrjMode(drawing::ProjectionMode_PERSPECTIVE),
192  mnDistance(1000),
193  mnFocalLength(1000),
194  mnShadowSlant(0),
195  mxShadeMode(drawing::ShadeMode_SMOOTH),
196  maAmbientColor(0x00666666),
197  mbLightingMode(false),
198  maVRP(0.0, 0.0, 1.0),
199  maVPN(0.0, 0.0, 1.0),
200  maVUP(0.0, 1.0, 0.0),
201  mbVRPUsed(false),
202  mbVPNUsed(false),
203  mbVUPUsed(false)
204 {
205 }
206 
208 SvXMLImportContext * SdXML3DSceneAttributesHelper::create3DLightContext( const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
209 {
210  const rtl::Reference<SdXML3DLightContext> xContext{new SdXML3DLightContext(mrImport, xAttrList)};
211 
212  // remember SdXML3DLightContext for later evaluation
213  maList.push_back(xContext);
214 
215  return xContext.get();
216 }
217 
220 {
221  auto nAttributeToken = aIter.getToken();
222  if( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_DR3D) )
223  return;
224 
225  switch(nAttributeToken & TOKEN_MASK)
226  {
227  case XML_TRANSFORM:
228  {
230  if(aTransform.NeedsAction())
231  mbSetTransform = aTransform.GetFullHomogenTransform(mxHomMat);
232  return;
233  }
234  case XML_VRP:
235  {
236  ::basegfx::B3DVector aNewVec;
238 
239  if(aNewVec != maVRP)
240  {
241  maVRP = aNewVec;
242  mbVRPUsed = true;
243  }
244  return;
245  }
246  case XML_VPN:
247  {
248  ::basegfx::B3DVector aNewVec;
250 
251  if(aNewVec != maVPN)
252  {
253  maVPN = aNewVec;
254  mbVPNUsed = true;
255  }
256  return;
257  }
258  case XML_VUP:
259  {
260  ::basegfx::B3DVector aNewVec;
262 
263  if(aNewVec != maVUP)
264  {
265  maVUP = aNewVec;
266  mbVUPUsed = true;
267  }
268  return;
269  }
270  case XML_PROJECTION:
271  {
272  if( IsXMLToken( aIter, XML_PARALLEL ) )
273  mxPrjMode = drawing::ProjectionMode_PARALLEL;
274  else
275  mxPrjMode = drawing::ProjectionMode_PERSPECTIVE;
276  return;
277  }
278  case XML_DISTANCE:
279  {
281  aIter.toView());
282  return;
283  }
284  case XML_FOCAL_LENGTH:
285  {
287  aIter.toView());
288  return;
289  }
290  case XML_SHADOW_SLANT:
291  {
293  return;
294  }
295  case XML_SHADE_MODE:
296  {
297  if( IsXMLToken( aIter, XML_FLAT ) )
298  mxShadeMode = drawing::ShadeMode_FLAT;
299  else if( IsXMLToken( aIter, XML_PHONG ) )
300  mxShadeMode = drawing::ShadeMode_PHONG;
301  else if( IsXMLToken( aIter, XML_GOURAUD ) )
302  mxShadeMode = drawing::ShadeMode_SMOOTH;
303  else
304  mxShadeMode = drawing::ShadeMode_DRAFT;
305  return;
306  }
307  case XML_AMBIENT_COLOR:
308  {
310  return;
311  }
312  case XML_LIGHTING_MODE:
313  {
315  return;
316  }
317  default:
318  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
319  }
320 }
321 
323 void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
324 {
325  uno::Any aAny;
326 
327  // world transformation
328  if(mbSetTransform)
329  {
330  xPropSet->setPropertyValue("D3DTransformMatrix", uno::Any(mxHomMat));
331  }
332 
333  // distance
334  xPropSet->setPropertyValue("D3DSceneDistance", uno::Any(mnDistance));
335  // focalLength
336  xPropSet->setPropertyValue("D3DSceneFocalLength", uno::Any(mnFocalLength));
337  // shadowSlant
338  xPropSet->setPropertyValue("D3DSceneShadowSlant", uno::Any(static_cast<sal_Int16>(mnShadowSlant)));
339  // shadeMode
340  xPropSet->setPropertyValue("D3DSceneShadeMode", uno::Any(mxShadeMode));
341  // ambientColor
342  xPropSet->setPropertyValue("D3DSceneAmbientColor", uno::Any(maAmbientColor));
343  // lightingMode
344  xPropSet->setPropertyValue("D3DSceneTwoSidedLighting", uno::Any(mbLightingMode));
345 
346  if( !maList.empty() )
347  {
348  uno::Any aAny2;
349  uno::Any aAny3;
350 
351  // set lights
352  for( size_t a = 0; a < maList.size(); a++)
353  {
354  SdXML3DLightContext* pCtx = maList[ a ].get();
355 
356  // set anys
357  aAny <<= pCtx->GetDiffuseColor();
358  drawing::Direction3D aLightDir;
359  aLightDir.DirectionX = pCtx->GetDirection().getX();
360  aLightDir.DirectionY = pCtx->GetDirection().getY();
361  aLightDir.DirectionZ = pCtx->GetDirection().getZ();
362  aAny2 <<= aLightDir;
363  aAny3 <<= pCtx->GetEnabled();
364 
365  switch(a)
366  {
367  case 0:
368  {
369  xPropSet->setPropertyValue("D3DSceneLightColor1", aAny);
370  xPropSet->setPropertyValue("D3DSceneLightDirection1", aAny2);
371  xPropSet->setPropertyValue("D3DSceneLightOn1", aAny3);
372  break;
373  }
374  case 1:
375  {
376  xPropSet->setPropertyValue("D3DSceneLightColor2", aAny);
377  xPropSet->setPropertyValue("D3DSceneLightDirection2", aAny2);
378  xPropSet->setPropertyValue("D3DSceneLightOn2", aAny3);
379  break;
380  }
381  case 2:
382  {
383  xPropSet->setPropertyValue("D3DSceneLightColor3", aAny);
384  xPropSet->setPropertyValue("D3DSceneLightDirection3", aAny2);
385  xPropSet->setPropertyValue("D3DSceneLightOn3", aAny3);
386  break;
387  }
388  case 3:
389  {
390  xPropSet->setPropertyValue("D3DSceneLightColor4", aAny);
391  xPropSet->setPropertyValue("D3DSceneLightDirection4", aAny2);
392  xPropSet->setPropertyValue("D3DSceneLightOn4", aAny3);
393  break;
394  }
395  case 4:
396  {
397  xPropSet->setPropertyValue("D3DSceneLightColor5", aAny);
398  xPropSet->setPropertyValue("D3DSceneLightDirection5", aAny2);
399  xPropSet->setPropertyValue("D3DSceneLightOn5", aAny3);
400  break;
401  }
402  case 5:
403  {
404  xPropSet->setPropertyValue("D3DSceneLightColor6", aAny);
405  xPropSet->setPropertyValue("D3DSceneLightDirection6", aAny2);
406  xPropSet->setPropertyValue("D3DSceneLightOn6", aAny3);
407  break;
408  }
409  case 6:
410  {
411  xPropSet->setPropertyValue("D3DSceneLightColor7", aAny);
412  xPropSet->setPropertyValue("D3DSceneLightDirection7", aAny2);
413  xPropSet->setPropertyValue("D3DSceneLightOn7", aAny3);
414  break;
415  }
416  case 7:
417  {
418  xPropSet->setPropertyValue("D3DSceneLightColor8", aAny);
419  xPropSet->setPropertyValue("D3DSceneLightDirection8", aAny2);
420  xPropSet->setPropertyValue("D3DSceneLightOn8", aAny3);
421  break;
422  }
423  }
424  }
425  }
426 
427  // CameraGeometry and camera settings
428  drawing::CameraGeometry aCamGeo;
429  aCamGeo.vrp.PositionX = maVRP.getX();
430  aCamGeo.vrp.PositionY = maVRP.getY();
431  aCamGeo.vrp.PositionZ = maVRP.getZ();
432  aCamGeo.vpn.DirectionX = maVPN.getX();
433  aCamGeo.vpn.DirectionY = maVPN.getY();
434  aCamGeo.vpn.DirectionZ = maVPN.getZ();
435  aCamGeo.vup.DirectionX = maVUP.getX();
436  aCamGeo.vup.DirectionY = maVUP.getY();
437  aCamGeo.vup.DirectionZ = maVUP.getZ();
438  xPropSet->setPropertyValue("D3DCameraGeometry", uno::Any(aCamGeo));
439 
440  // #91047# set drawing::ProjectionMode AFTER camera geometry is set
441  // projection "D3DScenePerspective" drawing::ProjectionMode
442  xPropSet->setPropertyValue("D3DScenePerspective", uno::Any(mxPrjMode));
443 }
444 
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetTransformation()
Definition: ximpshap.cxx:513
bool convertMeasureToCore(sal_Int32 &rValue, std::u16string_view 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
constexpr sal_uInt16 XML_NAMESPACE_DR3D
static SvXMLShapeContext * Create3DSceneChildContext(SvXMLImport &rImport, sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > const &rShapes)
sal_Int32 GetDiffuseColor() const
Definition: shapeimport.hxx:64
void setSceneAttributes(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
this sets the scene attributes at this propertyset
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:56
static bool convertB3DVector(::basegfx::B3DVector &rVector, std::u16string_view rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:591
void processSceneAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter &aIter)
this should be called for each scene attribute
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3462
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
SdXML3DSceneShapeContext(SvXMLImport &rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList, css::uno::Reference< css::drawing::XShapes > const &rShapes, bool bTemporaryShape)
Definition: ximp3dscene.cxx:94
sal_Int32 maDiffuseColor
Definition: shapeimport.hxx:53
SdXML3DLightContext(SvXMLImport &rImport, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
Definition: ximp3dscene.cxx:40
void AddShape(css::uno::Reference< css::drawing::XShape > &xShape)
css::uno::Reference< css::drawing::XShapes > mxChildren
Definition: ximp3dscene.hxx:33
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:110
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: ximpshap.cxx:320
bool GetEnabled() const
Definition: shapeimport.hxx:66
::basegfx::B3DVector maVUP
Definition: shapeimport.hxx:93
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
virtual ~SdXML3DLightContext() override
Definition: ximp3dscene.cxx:89
uno_Any a
css::drawing::ShadeMode mxShadeMode
Definition: shapeimport.hxx:87
::basegfx::B3DVector maVPN
Definition: shapeimport.hxx:92
SdXML3DSceneAttributesHelper(SvXMLImport &rImporter)
css::uno::Reference< css::drawing::XShape > mxShape
static bool convertColor(sal_Int32 &rColor, std::u16string_view rValue)
const ::basegfx::B3DVector & GetDirection() const
Definition: shapeimport.hxx:65
SvXMLImportContext * create3DLightContext(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
creates a 3d light context and adds it to the internal list for later processing
static bool convertBool(bool &rBool, std::u16string_view rString)
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:45
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
Definition: xmlimp.hxx:103
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:591
::basegfx::B3DVector maDirection
Definition: shapeimport.hxx:54
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:96
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:395
virtual ~SdXML3DSceneShapeContext() override
#define SAL_WARN(area, stream)
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:93
css::drawing::ProjectionMode mxPrjMode
Definition: shapeimport.hxx:83
::basegfx::B3DVector maVRP
Definition: shapeimport.hxx:91
virtual void SAL_CALL endFastElement(sal_Int32 nElement) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
Definition: ximpshap.cxx:326
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
::std::vector< rtl::Reference< SdXML3DLightContext > > maList
Definition: shapeimport.hxx:77
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:603
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
Definition: shapeimport.hxx:80
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo