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 <sal/log.hxx>
23 #include "ximp3dscene.hxx"
24 #include <xmloff/xmluconv.hxx>
25 #include <xexptran.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlnamespace.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/drawing/Direction3D.hpp>
30 #include <com/sun/star/drawing/CameraGeometry.hpp>
31 #include "eventimp.hxx"
32 #include "descriptionimp.hxx"
34 using namespace ::com::sun::star
;
35 using namespace ::xmloff::token
;
37 // dr3d:3dlight context
39 SdXML3DLightContext::SdXML3DLightContext(
41 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
42 : SvXMLImportContext( rImport
),
43 maDiffuseColor(0x00000000),
44 maDirection(0.0, 0.0, 1.0),
48 // read attributes for the 3DScene
49 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
51 switch(aIter
.getToken())
53 case XML_ELEMENT(DR3D
, XML_DIFFUSE_COLOR
):
55 ::sax::Converter::convertColor(maDiffuseColor
, aIter
.toView());
58 case XML_ELEMENT(DR3D
, XML_DIRECTION
):
60 ::basegfx::B3DVector aVal
;
61 SvXMLUnitConverter::convertB3DVector(aVal
, aIter
.toView());
62 if (!std::isnan(aVal
.getX()) && !std::isnan(aVal
.getY()) && !std::isnan(aVal
.getZ()))
68 SAL_WARN("xmloff", "NaNs found in light direction: " << aIter
.toString());
72 case XML_ELEMENT(DR3D
, XML_ENABLED
):
74 (void)::sax::Converter::convertBool(mbEnabled
, aIter
.toView());
77 case XML_ELEMENT(DR3D
, XML_SPECULAR
):
79 (void)::sax::Converter::convertBool(mbSpecular
, aIter
.toView());
83 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
88 SdXML3DLightContext::~SdXML3DLightContext()
93 SdXML3DSceneShapeContext::SdXML3DSceneShapeContext(
95 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
,
96 uno::Reference
< drawing::XShapes
> const & rShapes
,
97 bool bTemporaryShapes
)
98 : SdXMLShapeContext( rImport
, xAttrList
, rShapes
, bTemporaryShapes
), SdXML3DSceneAttributesHelper( rImport
)
102 SdXML3DSceneShapeContext::~SdXML3DSceneShapeContext()
106 void SdXML3DSceneShapeContext::startFastElement(
108 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
110 // create new 3DScene shape and add it to rShapes, use it
111 // as base for the new 3DScene import
112 AddShape( u
"com.sun.star.drawing.Shape3DSceneObject"_ustr
);
117 mxChildren
.set( mxShape
, uno::UNO_QUERY
);
118 if( mxChildren
.is() )
119 GetImport().GetShapeImport()->pushGroupForPostProcessing( mxChildren
);
123 // set pos, size, shear and rotate
127 // read attributes for the 3DScene
128 for( auto& aIter
: sax_fastparser::castToFastAttributeList(xAttrList
) )
129 processSceneAttribute( aIter
);
131 // #91047# call parent function is missing here, added it
135 SdXMLShapeContext::startFastElement(nElement
, xAttrList
);
139 void SdXML3DSceneShapeContext::endFastElement(sal_Int32 nElement
)
144 uno::Reference
< beans::XPropertySet
> xPropSet(mxShape
, uno::UNO_QUERY
);
147 setSceneAttributes( xPropSet
);
150 if( mxChildren
.is() )
151 GetImport().GetShapeImport()->popGroupAndPostProcess();
154 SdXMLShapeContext::endFastElement(nElement
);
157 css::uno::Reference
< css::xml::sax::XFastContextHandler
> SdXML3DSceneShapeContext::createFastChildContext(
159 const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
161 SvXMLImportContextRef xContext
;
165 case XML_ELEMENT(SVG
, XML_TITLE
):
166 case XML_ELEMENT(SVG_COMPAT
, XML_TITLE
):
167 case XML_ELEMENT(SVG
, XML_DESC
):
168 case XML_ELEMENT(SVG_COMPAT
, XML_DESC
):
169 xContext
= new SdXMLDescriptionContext( GetImport(), nElement
, mxShape
);
171 case XML_ELEMENT(OFFICE
, XML_EVENT_LISTENERS
):
172 xContext
= new SdXMLEventsContext( GetImport(), mxShape
);
174 // look for local light context first
175 case XML_ELEMENT(DR3D
, XML_LIGHT
):
176 // dr3d:light inside dr3d:scene context
177 xContext
= create3DLightContext( xAttrList
);
180 // call GroupChildContext function at common ShapeImport
181 return XMLShapeImportHelper::Create3DSceneChildContext(
182 GetImport(), nElement
, xAttrList
, mxChildren
);
187 SdXML3DSceneAttributesHelper::SdXML3DSceneAttributesHelper( SvXMLImport
& rImporter
)
188 : mrImport( rImporter
),
189 mbSetTransform( false ),
190 mxPrjMode(drawing::ProjectionMode_PERSPECTIVE
),
194 mxShadeMode(drawing::ShadeMode_SMOOTH
),
195 maAmbientColor(0x00666666),
196 mbLightingMode(false),
197 maVRP(0.0, 0.0, 1.0),
198 maVPN(0.0, 0.0, 1.0),
199 maVUP(0.0, 1.0, 0.0),
204 /** creates a 3d light context and adds it to the internal list for later processing */
205 SvXMLImportContext
* SdXML3DSceneAttributesHelper::create3DLightContext( const css::uno::Reference
< css::xml::sax::XFastAttributeList
>& xAttrList
)
207 const rtl::Reference
<SdXML3DLightContext
> xContext
{new SdXML3DLightContext(mrImport
, xAttrList
)};
209 // remember SdXML3DLightContext for later evaluation
210 maList
.push_back(xContext
);
212 return xContext
.get();
215 /** this should be called for each scene attribute */
216 void SdXML3DSceneAttributesHelper::processSceneAttribute( const sax_fastparser::FastAttributeList::FastAttributeIter
& aIter
)
218 auto nAttributeToken
= aIter
.getToken();
219 if( !IsTokenInNamespace(nAttributeToken
, XML_NAMESPACE_DR3D
) )
222 switch(nAttributeToken
& TOKEN_MASK
)
226 SdXMLImExTransform3D
aTransform(aIter
.toString(), mrImport
.GetMM100UnitConverter());
227 if(aTransform
.NeedsAction())
228 mbSetTransform
= aTransform
.GetFullHomogenTransform(mxHomMat
);
233 ::basegfx::B3DVector aNewVec
;
234 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
245 ::basegfx::B3DVector aNewVec
;
246 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
256 ::basegfx::B3DVector aNewVec
;
257 SvXMLUnitConverter::convertB3DVector(aNewVec
, aIter
.toView());
267 if( IsXMLToken( aIter
, XML_PARALLEL
) )
268 mxPrjMode
= drawing::ProjectionMode_PARALLEL
;
270 mxPrjMode
= drawing::ProjectionMode_PERSPECTIVE
;
275 mrImport
.GetMM100UnitConverter().convertMeasureToCore(mnDistance
,
279 case XML_FOCAL_LENGTH
:
281 mrImport
.GetMM100UnitConverter().convertMeasureToCore(mnFocalLength
,
285 case XML_SHADOW_SLANT
:
288 if (::sax::Converter::convertAngle(fAngle
, aIter
.toView()))
289 mnShadowSlant
= static_cast<sal_Int32
>(basegfx::fround(fAngle
));
296 if( IsXMLToken( aIter
, XML_FLAT
) )
297 mxShadeMode
= drawing::ShadeMode_FLAT
;
298 else if( IsXMLToken( aIter
, XML_PHONG
) )
299 mxShadeMode
= drawing::ShadeMode_PHONG
;
300 else if( IsXMLToken( aIter
, XML_GOURAUD
) )
301 mxShadeMode
= drawing::ShadeMode_SMOOTH
;
303 mxShadeMode
= drawing::ShadeMode_DRAFT
;
306 case XML_AMBIENT_COLOR
:
308 ::sax::Converter::convertColor(maAmbientColor
, aIter
.toView());
311 case XML_LIGHTING_MODE
:
313 (void)::sax::Converter::convertBool(mbLightingMode
, aIter
.toView());
317 XMLOFF_WARN_UNKNOWN("xmloff", aIter
);
321 /** this sets the scene attributes at this propertyset */
322 void SdXML3DSceneAttributesHelper::setSceneAttributes( const css::uno::Reference
< css::beans::XPropertySet
>& xPropSet
)
326 // world transformation
329 xPropSet
->setPropertyValue(u
"D3DTransformMatrix"_ustr
, uno::Any(mxHomMat
));
333 xPropSet
->setPropertyValue(u
"D3DSceneDistance"_ustr
, uno::Any(mnDistance
));
335 xPropSet
->setPropertyValue(u
"D3DSceneFocalLength"_ustr
, uno::Any(mnFocalLength
));
337 xPropSet
->setPropertyValue(u
"D3DSceneShadowSlant"_ustr
, uno::Any(static_cast<sal_Int16
>(mnShadowSlant
)));
339 xPropSet
->setPropertyValue(u
"D3DSceneShadeMode"_ustr
, uno::Any(mxShadeMode
));
341 xPropSet
->setPropertyValue(u
"D3DSceneAmbientColor"_ustr
, uno::Any(maAmbientColor
));
343 xPropSet
->setPropertyValue(u
"D3DSceneTwoSidedLighting"_ustr
, uno::Any(mbLightingMode
));
345 if( !maList
.empty() )
351 for( size_t a
= 0; a
< maList
.size(); a
++)
353 SdXML3DLightContext
* pCtx
= maList
[ a
].get();
356 aAny
<<= pCtx
->GetDiffuseColor();
357 drawing::Direction3D aLightDir
;
358 aLightDir
.DirectionX
= pCtx
->GetDirection().getX();
359 aLightDir
.DirectionY
= pCtx
->GetDirection().getY();
360 aLightDir
.DirectionZ
= pCtx
->GetDirection().getZ();
362 aAny3
<<= pCtx
->GetEnabled();
368 xPropSet
->setPropertyValue(u
"D3DSceneLightColor1"_ustr
, aAny
);
369 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection1"_ustr
, aAny2
);
370 xPropSet
->setPropertyValue(u
"D3DSceneLightOn1"_ustr
, aAny3
);
375 xPropSet
->setPropertyValue(u
"D3DSceneLightColor2"_ustr
, aAny
);
376 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection2"_ustr
, aAny2
);
377 xPropSet
->setPropertyValue(u
"D3DSceneLightOn2"_ustr
, aAny3
);
382 xPropSet
->setPropertyValue(u
"D3DSceneLightColor3"_ustr
, aAny
);
383 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection3"_ustr
, aAny2
);
384 xPropSet
->setPropertyValue(u
"D3DSceneLightOn3"_ustr
, aAny3
);
389 xPropSet
->setPropertyValue(u
"D3DSceneLightColor4"_ustr
, aAny
);
390 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection4"_ustr
, aAny2
);
391 xPropSet
->setPropertyValue(u
"D3DSceneLightOn4"_ustr
, aAny3
);
396 xPropSet
->setPropertyValue(u
"D3DSceneLightColor5"_ustr
, aAny
);
397 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection5"_ustr
, aAny2
);
398 xPropSet
->setPropertyValue(u
"D3DSceneLightOn5"_ustr
, aAny3
);
403 xPropSet
->setPropertyValue(u
"D3DSceneLightColor6"_ustr
, aAny
);
404 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection6"_ustr
, aAny2
);
405 xPropSet
->setPropertyValue(u
"D3DSceneLightOn6"_ustr
, aAny3
);
410 xPropSet
->setPropertyValue(u
"D3DSceneLightColor7"_ustr
, aAny
);
411 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection7"_ustr
, aAny2
);
412 xPropSet
->setPropertyValue(u
"D3DSceneLightOn7"_ustr
, aAny3
);
417 xPropSet
->setPropertyValue(u
"D3DSceneLightColor8"_ustr
, aAny
);
418 xPropSet
->setPropertyValue(u
"D3DSceneLightDirection8"_ustr
, aAny2
);
419 xPropSet
->setPropertyValue(u
"D3DSceneLightOn8"_ustr
, aAny3
);
426 // CameraGeometry and camera settings
427 drawing::CameraGeometry aCamGeo
;
428 aCamGeo
.vrp
.PositionX
= maVRP
.getX();
429 aCamGeo
.vrp
.PositionY
= maVRP
.getY();
430 aCamGeo
.vrp
.PositionZ
= maVRP
.getZ();
431 aCamGeo
.vpn
.DirectionX
= maVPN
.getX();
432 aCamGeo
.vpn
.DirectionY
= maVPN
.getY();
433 aCamGeo
.vpn
.DirectionZ
= maVPN
.getZ();
434 aCamGeo
.vup
.DirectionX
= maVUP
.getX();
435 aCamGeo
.vup
.DirectionY
= maVUP
.getY();
436 aCamGeo
.vup
.DirectionZ
= maVUP
.getZ();
437 xPropSet
->setPropertyValue(u
"D3DCameraGeometry"_ustr
, uno::Any(aCamGeo
));
439 // #91047# set drawing::ProjectionMode AFTER camera geometry is set
440 // projection "D3DScenePerspective" drawing::ProjectionMode
441 xPropSet
->setPropertyValue(u
"D3DScenePerspective"_ustr
, uno::Any(mxPrjMode
));
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */