1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sax/tools/converter.hxx>
21 #include <rtl/math.hxx>
22 #include <sal/log.hxx>
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"
35 using namespace ::com::sun::star
;
36 using namespace ::xmloff::token
;
38 // dr3d:3dlight context
40 SdXML3DLightContext::SdXML3DLightContext(
42 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
43 : SvXMLImportContext( rImport
),
44 maDiffuseColor(0x00000000),
45 maDirection(0.0, 0.0, 1.0),
49 // read attributes for the 3DScene
50 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
52 switch(aIter
.getToken())
54 case XML_ELEMENT(DR3D
, XML_DIFFUSE_COLOR
):
56 ::sax::Converter::convertColor(maDiffuseColor
, aIter
.toView());
59 case XML_ELEMENT(DR3D
, XML_DIRECTION
):
61 ::basegfx::B3DVector aVal
;
62 SvXMLUnitConverter::convertB3DVector(aVal
, aIter
.toView());
63 if (!std::isnan(aVal
.getX()) && !std::isnan(aVal
.getY()) && !std::isnan(aVal
.getZ()))
69 SAL_WARN("xmloff", "NaNs found in light direction: " << aIter
.toString());
73 case XML_ELEMENT(DR3D
, XML_ENABLED
):
75 (void)::sax::Converter::convertBool(mbEnabled
, aIter
.toView());
78 case XML_ELEMENT(DR3D
, XML_SPECULAR
):
80 (void)::sax::Converter::convertBool(mbSpecular
, aIter
.toView());
84 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
89 SdXML3DLightContext::~SdXML3DLightContext()
94 SdXML3DSceneShapeContext::SdXML3DSceneShapeContext(
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
)
103 SdXML3DSceneShapeContext::~SdXML3DSceneShapeContext()
107 void SdXML3DSceneShapeContext::startFastElement(
109 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
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" );
118 mxChildren
.set( mxShape
, uno::UNO_QUERY
);
119 if( mxChildren
.is() )
120 GetImport().GetShapeImport()->pushGroupForPostProcessing( mxChildren
);
124 // set pos, size, shear and rotate
128 // read attributes for the 3DScene
129 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
130 processSceneAttribute( aIter
);
132 // #91047# call parent function is missing here, added it
136 SdXMLShapeContext::startFastElement(nElement
, xAttrList
);
140 void SdXML3DSceneShapeContext::endFastElement(sal_Int32 nElement
)
145 uno::Reference
< beans::XPropertySet
> xPropSet(mxShape
, uno::UNO_QUERY
);
148 setSceneAttributes( xPropSet
);
151 if( mxChildren
.is() )
152 GetImport().GetShapeImport()->popGroupAndPostProcess();
155 SdXMLShapeContext::endFastElement(nElement
);
158 css::uno::Reference
< css::xml::sax::XFastContextHandler
> SdXML3DSceneShapeContext::createFastChildContext(
160 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
162 SvXMLImportContextRef xContext
;
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
);
172 case XML_ELEMENT(OFFICE
, XML_EVENT_LISTENERS
):
173 xContext
= new SdXMLEventsContext( GetImport(), mxShape
);
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
);
181 // call GroupChildContext function at common ShapeImport
182 return XMLShapeImportHelper::Create3DSceneChildContext(
183 GetImport(), nElement
, xAttrList
, mxChildren
);
188 SdXML3DSceneAttributesHelper::SdXML3DSceneAttributesHelper( SvXMLImport
& rImporter
)
189 : mrImport( rImporter
),
190 mbSetTransform( false ),
191 mxPrjMode(drawing::ProjectionMode_PERSPECTIVE
),
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),
205 /** creates a 3d light context and adds it to the internal list for later processing */
206 SvXMLImportContext
* SdXML3DSceneAttributesHelper::create3DLightContext( const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
208 const rtl::Reference
<SdXML3DLightContext
> xContext
{new SdXML3DLightContext(mrImport
, xAttrList
)};
210 // remember SdXML3DLightContext for later evaluation
211 maList
.push_back(xContext
);
213 return xContext
.get();
216 /** this should be called for each scene attribute */
217 void SdXML3DSceneAttributesHelper::processSceneAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
219 auto nAttributeToken
= aIter
.getToken();
220 if( !IsTokenInNamespace(nAttributeToken
, XML_NAMESPACE_DR3D
) )
223 switch(nAttributeToken
& TOKEN_MASK
)
227 SdXMLImExTransform3D
aTransform(aIter
.toString(), mrImport
.GetMM100UnitConverter());
228 if(aTransform
.NeedsAction())
229 mbSetTransform
= aTransform
.GetFullHomogenTransform(mxHomMat
);
234 ::basegfx::B3DVector aNewVec
;
235 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
246 ::basegfx::B3DVector aNewVec
;
247 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
257 ::basegfx::B3DVector aNewVec
;
258 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
268 if( IsXMLToken( aIter
, XML_PARALLEL
) )
269 mxPrjMode
= drawing::ProjectionMode_PARALLEL
;
271 mxPrjMode
= drawing::ProjectionMode_PERSPECTIVE
;
276 mrImport
.GetMM100UnitConverter().convertMeasureToCore(mnDistance
,
280 case XML_FOCAL_LENGTH
:
282 mrImport
.GetMM100UnitConverter().convertMeasureToCore(mnFocalLength
,
286 case XML_SHADOW_SLANT
:
288 ::sax::Converter::convertNumber(mnShadowSlant
, aIter
.toView());
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
;
300 mxShadeMode
= drawing::ShadeMode_DRAFT
;
303 case XML_AMBIENT_COLOR
:
305 ::sax::Converter::convertColor(maAmbientColor
, aIter
.toView());
308 case XML_LIGHTING_MODE
:
310 (void)::sax::Converter::convertBool(mbLightingMode
, aIter
.toView());
314 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
318 /** this sets the scene attributes at this propertyset */
319 void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference
< css::beans::XPropertySet
>& xPropSet
)
323 // world transformation
326 xPropSet
->setPropertyValue("D3DTransformMatrix", uno::Any(mxHomMat
));
330 xPropSet
->setPropertyValue("D3DSceneDistance", uno::Any(mnDistance
));
332 xPropSet
->setPropertyValue("D3DSceneFocalLength", uno::Any(mnFocalLength
));
334 xPropSet
->setPropertyValue("D3DSceneShadowSlant", uno::Any(static_cast<sal_Int16
>(mnShadowSlant
)));
336 xPropSet
->setPropertyValue("D3DSceneShadeMode", uno::Any(mxShadeMode
));
338 xPropSet
->setPropertyValue("D3DSceneAmbientColor", uno::Any(maAmbientColor
));
340 xPropSet
->setPropertyValue("D3DSceneTwoSidedLighting", uno::Any(mbLightingMode
));
342 if( !maList
.empty() )
348 for( size_t a
= 0; a
< maList
.size(); a
++)
350 SdXML3DLightContext
* pCtx
= maList
[ a
].get();
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();
359 aAny3
<<= pCtx
->GetEnabled();
365 xPropSet
->setPropertyValue("D3DSceneLightColor1", aAny
);
366 xPropSet
->setPropertyValue("D3DSceneLightDirection1", aAny2
);
367 xPropSet
->setPropertyValue("D3DSceneLightOn1", aAny3
);
372 xPropSet
->setPropertyValue("D3DSceneLightColor2", aAny
);
373 xPropSet
->setPropertyValue("D3DSceneLightDirection2", aAny2
);
374 xPropSet
->setPropertyValue("D3DSceneLightOn2", aAny3
);
379 xPropSet
->setPropertyValue("D3DSceneLightColor3", aAny
);
380 xPropSet
->setPropertyValue("D3DSceneLightDirection3", aAny2
);
381 xPropSet
->setPropertyValue("D3DSceneLightOn3", aAny3
);
386 xPropSet
->setPropertyValue("D3DSceneLightColor4", aAny
);
387 xPropSet
->setPropertyValue("D3DSceneLightDirection4", aAny2
);
388 xPropSet
->setPropertyValue("D3DSceneLightOn4", aAny3
);
393 xPropSet
->setPropertyValue("D3DSceneLightColor5", aAny
);
394 xPropSet
->setPropertyValue("D3DSceneLightDirection5", aAny2
);
395 xPropSet
->setPropertyValue("D3DSceneLightOn5", aAny3
);
400 xPropSet
->setPropertyValue("D3DSceneLightColor6", aAny
);
401 xPropSet
->setPropertyValue("D3DSceneLightDirection6", aAny2
);
402 xPropSet
->setPropertyValue("D3DSceneLightOn6", aAny3
);
407 xPropSet
->setPropertyValue("D3DSceneLightColor7", aAny
);
408 xPropSet
->setPropertyValue("D3DSceneLightDirection7", aAny2
);
409 xPropSet
->setPropertyValue("D3DSceneLightOn7", aAny3
);
414 xPropSet
->setPropertyValue("D3DSceneLightColor8", aAny
);
415 xPropSet
->setPropertyValue("D3DSceneLightDirection8", aAny2
);
416 xPropSet
->setPropertyValue("D3DSceneLightOn8", aAny3
);
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
));
436 // #91047# set drawing::ProjectionMode AFTER camera geometry is set
437 // projection "D3DScenePerspective" drawing::ProjectionMode
438 xPropSet
->setPropertyValue("D3DScenePerspective", uno::Any(mxPrjMode
));
441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */