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;
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 {
203 }
204 
206 SvXMLImportContext * SdXML3DSceneAttributesHelper::create3DLightContext( const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList)
207 {
208  const rtl::Reference<SdXML3DLightContext> xContext{new SdXML3DLightContext(mrImport, xAttrList)};
209 
210  // remember SdXML3DLightContext for later evaluation
211  maList.push_back(xContext);
212 
213  return xContext.get();
214 }
215 
218 {
219  auto nAttributeToken = aIter.getToken();
220  if( !IsTokenInNamespace(nAttributeToken, XML_NAMESPACE_DR3D) )
221  return;
222 
223  switch(nAttributeToken & TOKEN_MASK)
224  {
225  case XML_TRANSFORM:
226  {
228  if(aTransform.NeedsAction())
229  mbSetTransform = aTransform.GetFullHomogenTransform(mxHomMat);
230  return;
231  }
232  case XML_VRP:
233  {
234  ::basegfx::B3DVector aNewVec;
236 
237  if(aNewVec != maVRP)
238  {
239  maVRP = aNewVec;
240  mbVRPUsed = true;
241  }
242  return;
243  }
244  case XML_VPN:
245  {
246  ::basegfx::B3DVector aNewVec;
248 
249  if(aNewVec != maVPN)
250  {
251  maVPN = aNewVec;
252  }
253  return;
254  }
255  case XML_VUP:
256  {
257  ::basegfx::B3DVector aNewVec;
259 
260  if(aNewVec != maVUP)
261  {
262  maVUP = aNewVec;
263  }
264  return;
265  }
266  case XML_PROJECTION:
267  {
268  if( IsXMLToken( aIter, XML_PARALLEL ) )
269  mxPrjMode = drawing::ProjectionMode_PARALLEL;
270  else
271  mxPrjMode = drawing::ProjectionMode_PERSPECTIVE;
272  return;
273  }
274  case XML_DISTANCE:
275  {
277  aIter.toView());
278  return;
279  }
280  case XML_FOCAL_LENGTH:
281  {
283  aIter.toView());
284  return;
285  }
286  case XML_SHADOW_SLANT:
287  {
289  return;
290  }
291  case XML_SHADE_MODE:
292  {
293  if( IsXMLToken( aIter, XML_FLAT ) )
294  mxShadeMode = drawing::ShadeMode_FLAT;
295  else if( IsXMLToken( aIter, XML_PHONG ) )
296  mxShadeMode = drawing::ShadeMode_PHONG;
297  else if( IsXMLToken( aIter, XML_GOURAUD ) )
298  mxShadeMode = drawing::ShadeMode_SMOOTH;
299  else
300  mxShadeMode = drawing::ShadeMode_DRAFT;
301  return;
302  }
303  case XML_AMBIENT_COLOR:
304  {
306  return;
307  }
308  case XML_LIGHTING_MODE:
309  {
311  return;
312  }
313  default:
314  XMLOFF_WARN_UNKNOWN("xmloff", aIter);
315  }
316 }
317 
319 void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
320 {
321  uno::Any aAny;
322 
323  // world transformation
324  if(mbSetTransform)
325  {
326  xPropSet->setPropertyValue("D3DTransformMatrix", uno::Any(mxHomMat));
327  }
328 
329  // distance
330  xPropSet->setPropertyValue("D3DSceneDistance", uno::Any(mnDistance));
331  // focalLength
332  xPropSet->setPropertyValue("D3DSceneFocalLength", uno::Any(mnFocalLength));
333  // shadowSlant
334  xPropSet->setPropertyValue("D3DSceneShadowSlant", uno::Any(static_cast<sal_Int16>(mnShadowSlant)));
335  // shadeMode
336  xPropSet->setPropertyValue("D3DSceneShadeMode", uno::Any(mxShadeMode));
337  // ambientColor
338  xPropSet->setPropertyValue("D3DSceneAmbientColor", uno::Any(maAmbientColor));
339  // lightingMode
340  xPropSet->setPropertyValue("D3DSceneTwoSidedLighting", uno::Any(mbLightingMode));
341 
342  if( !maList.empty() )
343  {
344  uno::Any aAny2;
345  uno::Any aAny3;
346 
347  // set lights
348  for( size_t a = 0; a < maList.size(); a++)
349  {
350  SdXML3DLightContext* pCtx = maList[ a ].get();
351 
352  // set anys
353  aAny <<= pCtx->GetDiffuseColor();
354  drawing::Direction3D aLightDir;
355  aLightDir.DirectionX = pCtx->GetDirection().getX();
356  aLightDir.DirectionY = pCtx->GetDirection().getY();
357  aLightDir.DirectionZ = pCtx->GetDirection().getZ();
358  aAny2 <<= aLightDir;
359  aAny3 <<= pCtx->GetEnabled();
360 
361  switch(a)
362  {
363  case 0:
364  {
365  xPropSet->setPropertyValue("D3DSceneLightColor1", aAny);
366  xPropSet->setPropertyValue("D3DSceneLightDirection1", aAny2);
367  xPropSet->setPropertyValue("D3DSceneLightOn1", aAny3);
368  break;
369  }
370  case 1:
371  {
372  xPropSet->setPropertyValue("D3DSceneLightColor2", aAny);
373  xPropSet->setPropertyValue("D3DSceneLightDirection2", aAny2);
374  xPropSet->setPropertyValue("D3DSceneLightOn2", aAny3);
375  break;
376  }
377  case 2:
378  {
379  xPropSet->setPropertyValue("D3DSceneLightColor3", aAny);
380  xPropSet->setPropertyValue("D3DSceneLightDirection3", aAny2);
381  xPropSet->setPropertyValue("D3DSceneLightOn3", aAny3);
382  break;
383  }
384  case 3:
385  {
386  xPropSet->setPropertyValue("D3DSceneLightColor4", aAny);
387  xPropSet->setPropertyValue("D3DSceneLightDirection4", aAny2);
388  xPropSet->setPropertyValue("D3DSceneLightOn4", aAny3);
389  break;
390  }
391  case 4:
392  {
393  xPropSet->setPropertyValue("D3DSceneLightColor5", aAny);
394  xPropSet->setPropertyValue("D3DSceneLightDirection5", aAny2);
395  xPropSet->setPropertyValue("D3DSceneLightOn5", aAny3);
396  break;
397  }
398  case 5:
399  {
400  xPropSet->setPropertyValue("D3DSceneLightColor6", aAny);
401  xPropSet->setPropertyValue("D3DSceneLightDirection6", aAny2);
402  xPropSet->setPropertyValue("D3DSceneLightOn6", aAny3);
403  break;
404  }
405  case 6:
406  {
407  xPropSet->setPropertyValue("D3DSceneLightColor7", aAny);
408  xPropSet->setPropertyValue("D3DSceneLightDirection7", aAny2);
409  xPropSet->setPropertyValue("D3DSceneLightOn7", aAny3);
410  break;
411  }
412  case 7:
413  {
414  xPropSet->setPropertyValue("D3DSceneLightColor8", aAny);
415  xPropSet->setPropertyValue("D3DSceneLightDirection8", aAny2);
416  xPropSet->setPropertyValue("D3DSceneLightOn8", aAny3);
417  break;
418  }
419  }
420  }
421  }
422 
423  // CameraGeometry and camera settings
424  drawing::CameraGeometry aCamGeo;
425  aCamGeo.vrp.PositionX = maVRP.getX();
426  aCamGeo.vrp.PositionY = maVRP.getY();
427  aCamGeo.vrp.PositionZ = maVRP.getZ();
428  aCamGeo.vpn.DirectionX = maVPN.getX();
429  aCamGeo.vpn.DirectionY = maVPN.getY();
430  aCamGeo.vpn.DirectionZ = maVPN.getZ();
431  aCamGeo.vup.DirectionX = maVUP.getX();
432  aCamGeo.vup.DirectionY = maVUP.getY();
433  aCamGeo.vup.DirectionZ = maVUP.getZ();
434  xPropSet->setPropertyValue("D3DCameraGeometry", uno::Any(aCamGeo));
435 
436  // #91047# set drawing::ProjectionMode AFTER camera geometry is set
437  // projection "D3DScenePerspective" drawing::ProjectionMode
438  xPropSet->setPropertyValue("D3DScenePerspective", uno::Any(mxPrjMode));
439 }
440 
441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void SetTransformation()
Definition: ximpshap.cxx:510
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:186
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:65
void setSceneAttributes(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
this sets the scene attributes at this propertyset
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:59
static bool convertB3DVector(::basegfx::B3DVector &rVector, std::u16string_view rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:606
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:3508
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:54
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:32
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:113
virtual void SAL_CALL startFastElement(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList) override
Definition: ximpshap.cxx:319
double getY() const
bool GetEnabled() const
Definition: shapeimport.hxx:67
double getZ() const
::basegfx::B3DVector maVUP
Definition: shapeimport.hxx:94
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:88
::basegfx::B3DVector maVPN
Definition: shapeimport.hxx:93
double getX() const
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:66
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:44
constexpr bool IsTokenInNamespace(sal_Int32 nToken, sal_uInt16 nNamespacePrefix)
Definition: xmlimp.hxx:104
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:588
::basegfx::B3DVector maDirection
Definition: shapeimport.hxx:55
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
const SvXMLUnitConverter & GetMM100UnitConverter() const
Definition: xmlimp.hxx:400
virtual ~SdXML3DSceneShapeContext() override
#define SAL_WARN(area, stream)
constexpr sal_Int32 TOKEN_MASK
Definition: xmlimp.hxx:94
css::drawing::ProjectionMode mxPrjMode
Definition: shapeimport.hxx:84
::basegfx::B3DVector maVRP
Definition: shapeimport.hxx:92
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:325
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:78
rtl::Reference< XMLShapeImportHelper > const & GetShapeImport()
Definition: xmlimp.hxx:608
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:81
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo